-- | -- -- Copyright : (C) Keera Studios Ltd, 2013 -- License : BSD3 -- Maintainer : support@keera.co.uk module Hails.MVC.View.HTML where import Control.Applicative ((<$>)) import Control.Monad (void) import Control.Monad.IO.Class (liftIO) import Control.Monad.Reader (ask) import Data.CBMVar (installCallbackCBMVar, newCBMVar, readCBMVar, writeCBMVar) import Data.CBMVar.Reactive (cbmvarReactiveRO, cbmvarReactiveRW) import Data.ReactiveValue import Data.String import GHCJS.DOM.Element (IsElement, setInnerHTML) import GHCJS.DOM.EventM (mouseButton, mouseClientXY, on) import GHCJS.DOM.EventTargetClosures (EventName, unsafeEventName) import GHCJS.DOM.GlobalEventHandlers (input, mouseDown, mouseMove) import GHCJS.DOM.HTMLElement (setInnerText) import GHCJS.DOM.HTMLInputElement (getValue, setValue) import GHCJS.DOM.HTMLParagraphElement (HTMLParagraphElement (..)) import GHCJS.DOM.MessageEvent (getData) import GHCJS.DOM.Types (HTMLElement, HTMLInputElement (..), IsGlobalEventHandlers, IsHTMLElement, JSString, MouseEvent, fromJSValUnchecked, toHTMLElement, toJSString) import GHCJS.DOM.WebSocket (WebSocket, message, sendString) -- * GHCJS DOM Reactive API inputTextReactive :: HTMLInputElement -> ReactiveFieldReadWrite IO String inputTextReactive x = ReactiveFieldReadWrite setter getter notifier where setter = setValue x getter = getValue x notifier p = void $ on x input (liftIO p) htmlElementClick :: IsHTMLElement e => e -> ReactiveFieldRead IO () htmlElementClick e = ReactiveFieldRead (return ()) (\p -> void $ on e' click (liftIO p)) where e' = toHTMLElement e click :: EventName HTMLElement MouseEvent click = unsafeEventName (toJSString "click") paragraphTextReactive :: HTMLParagraphElement -> ReactiveFieldWrite IO String paragraphTextReactive x = ReactiveFieldWrite setter where setter = setInnerHTML x websocketReactive :: WebSocket -> IO (ReactiveFieldReadWrite IO String) websocketReactive socket = do p <- newCBMVar "" void $ on socket message (ask >>= \dt -> getData dt >>= \js -> liftIO (fromJSValUnchecked js) >>= \jss -> liftIO (writeCBMVar p (show (jss :: JSString)))) let getter = readCBMVar p notifier n = installCallbackCBMVar p n setter x = do sendString socket (fromString x :: JSString) writeCBMVar p x return (ReactiveFieldReadWrite setter getter notifier) mouseDownReactive :: (IsGlobalEventHandlers a, IsElement a) => a -> ReactiveFieldRead IO () mouseDownReactive s = eventR $ \p -> void $ on s mouseDown (liftIO p) mousePosElementReactive :: (IsGlobalEventHandlers e, IsElement e) => e -> IO (ReactiveFieldRead IO (Int, Int)) mousePosElementReactive e = do p <- newCBMVar (0,0) void $ on e mouseMove (mouseClientXY >>= \pos -> liftIO (writeCBMVar p pos)) return (cbmvarReactiveRO p)