module DOMCalc where import UnsafeJS import Control.Monad import Control.Monad.JS import DOM.Level1.Dom import DOM.Level1.Html import DOM.Level1.Node import DOM.Level1.HTMLBRElement import DOM.Level1.HTMLDivElement import DOM.Level1.HTMLPreElement import DOM.Level1.HTMLButtonElement as B import DOM.Level1.HTMLInputElement as I import CDOM.Level1.DomUtils import CDOM.Level1.Events import Data.JSRef putStatus :: a -> JS a putStatus a = return (putStatus' a) putStatus' a = unsafeJS "window.status=exprEval(a).toString();return a;" -- A simple calculator demo done with the DOM framework -- Make a button with text on it mkButtonText :: THTMLDocument -> String -> JS THTMLButtonElement mkButtonText doc txt = do d <- mkDiv doc pr <- mkPre doc tx <- mkText doc txt btn <- mkButton doc >>= B.set'value txt addChild tx pr addChild pr d addChild d btn -- Make a calculator widget -- A handler for button press. It basically contains the whole functionality -- of the calculator, processing events coming from buttons and modifying -- the visible input element. Another (hidden) input element -- is used as a temporary storage. Value of the event per se is not used. btnDown :: THTMLButtonElement -> THTMLInputElement -> JSRef CalcST -> a -> JS Bool btnDown btn inp cst evt = do val <- B.get'value btn case val of [] -> return False op -> do processOp op inp cst return False -- Process an operation from a button press processOp :: String -> THTMLInputElement -> JSRef CalcST -> JS () processOp op inp cst = do st <- readJSRef cst case (op `elem` ["+", "-", "*", "/", "=", "C"]) of True -> case op of "=" -> case opsv st of "" -> return () _ -> do iv <- I.get'value inp let ivn = read iv :: Int res = (case opsv st of "+" -> (+) "-" -> (-) "*" -> (*) "/" -> div) (inpsv st) ivn I.set'value (show res) inp writeJSRef cst clear return () "C" -> do I.set'value "" inp writeJSRef cst clear return () _ -> do v <- I.get'value inp writeJSRef cst st {inpsv = read v, opsv = op, inprst = True} return () False -> do v <- I.get'value inp let nv = case inprst st of True -> op False -> v ++ op I.set'value nv inp writeJSRef cst st {inprst = False} return () data CalcST = CalcST {inpsv :: Int, zz:: String, opsv :: String, inprst :: Bool} deriving (Show) clear = CalcST {inpsv = 0, opsv = "", inprst = False} mkCalc :: THTMLDocument -> JS THTMLDivElement mkCalc doc = do calc <- mkDiv doc inp <- mkInput doc cst <- newJSRef clear divi <- mkDiv doc addChild inp divi let onebtn txt = do b <- mkButtonText doc txt set'on "click" (btnDown b inp cst) b divs <- mapM (\a -> do btns <- mapM onebtn a d <- mkDiv doc mapM_ (flip addChild d) btns return d ) [["1", "2", "3", "+"], ["4", "5", "6", "-"], ["7", "8", "9", "*"], ["0", "C", "=", "/"]] mapM_ (flip addChild calc) (divi:divs) return calc main :: JS () main = do doc <- getHTMLDocument dbody <- documentBody doc calc <- mkCalc doc -- calc2 <- mkCalc doc addChild calc dbody -- >>= addChild calc2 return ()