{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE ConstraintKinds #-} module JSDOM.EventM ( EventM(..) , SaferEventListener(..) , EventName , newListener , newListenerSync , newListenerAsync , addListener , removeListener , releaseListener , on , event , eventTarget , target , eventCurrentTarget , eventPhase , bubbles , cancelable , timeStamp , stopPropagation , preventDefault , defaultPrevented , stopImmediatePropagation , srcElement , getCancelBubble , cancelBubble , getReturnValue , returnValue , uiView , uiDetail , uiKeyCode , uiCharCode , uiLayerX , uiLayerY , uiLayerXY , uiPageX , uiPageY , uiPageXY , uiWhich , mouseScreenX , mouseScreenY , mouseScreenXY , mouseClientX , mouseClientY , mouseClientXY , mouseMovementX , mouseMovementY , mouseMovementXY , mouseCtrlKey , mouseShiftKey , mouseAltKey , mouseMetaKey , mouseButton , mouseRelatedTarget , mouseOffsetX , mouseOffsetY , mouseOffsetXY , mouseX , mouseY , mouseXY , mouseFromElement , mouseToElement ) where import Control.Applicative ((<$>)) import Control.Monad (join) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.Trans.Reader (ReaderT, ask, runReaderT) import JSDOM.Types import qualified JSDOM.Generated.Event as Event import qualified JSDOM.Generated.UIEvent as UIEvent import qualified JSDOM.Generated.MouseEvent as MouseEvent import qualified JSDOM.Generated.KeyboardEvent as KeyboardEvent import JSDOM.Generated.EventTarget import JSDOM.EventTargetClosures import Data.Word (Word) import Data.Foldable (forM_) import Data.Traversable (mapM) import Data.Coerce (coerce) type EventM t e = ReaderT e DOM newListener :: (IsEvent e) => EventM t e () -> DOM (SaferEventListener t e) newListener f = eventListenerNew (runReaderT f) newListenerSync :: (IsEvent e) => EventM t e () -> DOM (SaferEventListener t e) newListenerSync f = eventListenerNewSync (runReaderT f) newListenerAsync :: (IsEvent e) => EventM t e () -> DOM (SaferEventListener t e) newListenerAsync f = eventListenerNewAsync (runReaderT f) addListener :: (IsEventTarget t, IsEvent e) => t -> EventName t e -> SaferEventListener t e -> Bool -> DOM () addListener target (EventName eventName) l useCapture = do raw <- EventListener <$> toJSVal l addEventListener target eventName (Just raw) useCapture removeListener :: (IsEventTarget t, IsEvent e) => t -> EventName t e -> SaferEventListener t e -> Bool -> DOM () removeListener target (EventName eventName) l useCapture = do raw <- EventListener <$> toJSVal l removeEventListener target eventName (Just raw) useCapture releaseListener :: (IsEventTarget t, IsEvent e) => SaferEventListener t e -> DOM () releaseListener = eventListenerRelease on :: (IsEventTarget t, IsEvent e) => t -> EventName t e -> EventM t e () -> DOM (DOM ()) on target eventName callback = do l <- newListener callback addListener target eventName l False return $ do removeListener target eventName l False releaseListener l onThese :: (IsEventTarget t, IsEvent e) => [(t, EventName t e)] -> EventM t e () -> DOM (DOM ()) onThese targetsAndEventNames callback = do l <- newListener callback forM_ targetsAndEventNames $ \(target, eventName) -> addListener target eventName l False return (do forM_ targetsAndEventNames (\(target, eventName) -> removeListener target eventName l False) releaseListener l) event :: EventM t e e event = ask eventTarget :: IsEvent e => EventM t e (Maybe EventTarget) eventTarget = event >>= (lift . Event.getTarget) eventTargetUnsafe :: IsEvent e => EventM t e EventTarget eventTargetUnsafe = event >>= (lift . Event.getTargetUnsafe) eventTargetUnchecked :: IsEvent e => EventM t e EventTarget eventTargetUnchecked = event >>= (lift . Event.getTargetUnchecked) target :: (IsEvent e, IsGObject t) => EventM t e (Maybe t) target = eventTarget >>= mapM (liftJSM . fromJSValUnchecked . coerce) targetUnsafe :: (IsEvent e, IsGObject t) => EventM t e t targetUnsafe = eventTargetUnsafe >>= (liftJSM . fromJSValUnchecked . coerce) targetUnchecked :: (IsEvent e, IsGObject t) => EventM t e t targetUnchecked = eventTargetUnchecked >>= (liftJSM . fromJSValUnchecked . coerce) eventCurrentTarget :: IsEvent e => EventM t e (Maybe EventTarget) eventCurrentTarget = event >>= (lift . Event.getCurrentTarget) eventCurrentTargetUnsafe :: IsEvent e => EventM t e EventTarget eventCurrentTargetUnsafe = event >>= (lift . Event.getCurrentTargetUnsafe) eventCurrentTargetUnchecked :: IsEvent e => EventM t e EventTarget eventCurrentTargetUnchecked = event >>= (lift . Event.getCurrentTargetUnchecked) eventPhase :: IsEvent e => EventM t e Word eventPhase = event >>= (lift . Event.getEventPhase) bubbles :: IsEvent e => EventM t e Bool bubbles = event >>= (lift . Event.getBubbles) cancelable :: IsEvent e => EventM t e Bool cancelable = event >>= (lift . Event.getCancelable) timeStamp :: IsEvent e => EventM t e Word timeStamp = event >>= (lift . Event.getTimeStamp) stopPropagation :: IsEvent e => EventM t e () stopPropagation = event >>= (lift . Event.stopPropagation) preventDefault :: IsEvent e => EventM t e () preventDefault = event >>= (lift . Event.preventDefault) defaultPrevented :: IsEvent e => EventM t e Bool defaultPrevented = event >>= (lift . Event.getDefaultPrevented) stopImmediatePropagation :: IsEvent e => EventM t e () stopImmediatePropagation = event >>= (lift . Event.stopImmediatePropagation) srcElement :: IsEvent e => EventM t e EventTarget srcElement = event >>= (lift . Event.getSrcElement) getCancelBubble :: IsEvent e => EventM t e Bool getCancelBubble = event >>= (lift . Event.getCancelBubble) cancelBubble :: IsEvent e => Bool -> EventM t e () cancelBubble f = event >>= (lift . flip Event.setCancelBubble f) getReturnValue :: IsEvent e => EventM t e Bool getReturnValue = event >>= (lift . Event.getReturnValue) returnValue :: IsEvent e => Bool -> EventM t e () returnValue f = event >>= (lift . flip Event.setReturnValue f) uiView :: IsUIEvent e => EventM t e Window uiView = event >>= (lift . UIEvent.getView) uiDetail :: IsUIEvent e => EventM t e Int uiDetail = event >>= (lift . UIEvent.getDetail) uiKeyCode :: EventM t KeyboardEvent Word uiKeyCode = event >>= (lift . KeyboardEvent.getKeyCode) uiCharCode :: EventM t KeyboardEvent Word uiCharCode = event >>= (lift . KeyboardEvent.getCharCode) uiLayerX :: IsUIEvent e => EventM t e Int uiLayerX = event >>= (lift . UIEvent.getLayerX) uiLayerY :: IsUIEvent e => EventM t e Int uiLayerY = event >>= (lift . UIEvent.getLayerY) uiLayerXY :: IsUIEvent e => EventM t e (Int, Int) uiLayerXY = do e <- event x <- lift $ UIEvent.getLayerX e y <- lift $ UIEvent.getLayerY e return (x, y) uiPageX :: IsUIEvent e => EventM t e Int uiPageX = event >>= (lift . UIEvent.getPageX) uiPageY :: IsUIEvent e => EventM t e Int uiPageY = event >>= (lift . UIEvent.getPageY) uiPageXY :: IsUIEvent e => EventM t e (Int, Int) uiPageXY = do e <- event x <- lift $ UIEvent.getPageX e y <- lift $ UIEvent.getPageY e return (x, y) uiWhich :: IsUIEvent e => EventM t e Int uiWhich = event >>= (lift . UIEvent.getWhich) mouseScreenX :: IsMouseEvent e => EventM t e Int mouseScreenX = event >>= (lift . MouseEvent.getScreenX) mouseScreenY :: IsMouseEvent e => EventM t e Int mouseScreenY = event >>= (lift . MouseEvent.getScreenY) mouseScreenXY :: IsMouseEvent e => EventM t e (Int, Int) mouseScreenXY = do e <- event x <- lift $ MouseEvent.getScreenX e y <- lift $ MouseEvent.getScreenY e return (x, y) mouseClientX :: IsMouseEvent e => EventM t e Int mouseClientX = event >>= (lift . MouseEvent.getClientX) mouseClientY :: IsMouseEvent e => EventM t e Int mouseClientY = event >>= (lift . MouseEvent.getClientY) mouseClientXY :: IsMouseEvent e => EventM t e (Int, Int) mouseClientXY = do e <- event x <- lift $ MouseEvent.getClientX e y <- lift $ MouseEvent.getClientY e return (x, y) mouseMovementX :: IsMouseEvent e => EventM t e Int mouseMovementX = event >>= (lift . MouseEvent.getMovementX) mouseMovementY :: IsMouseEvent e => EventM t e Int mouseMovementY = event >>= (lift . MouseEvent.getMovementY) mouseMovementXY :: IsMouseEvent e => EventM t e (Int, Int) mouseMovementXY = do e <- event x <- lift $ MouseEvent.getMovementX e y <- lift $ MouseEvent.getMovementY e return (x, y) mouseCtrlKey :: IsMouseEvent e => EventM t e Bool mouseCtrlKey = event >>= (lift . MouseEvent.getCtrlKey) mouseShiftKey :: IsMouseEvent e => EventM t e Bool mouseShiftKey = event >>= (lift . MouseEvent.getShiftKey) mouseAltKey :: IsMouseEvent e => EventM t e Bool mouseAltKey = event >>= (lift . MouseEvent.getAltKey) mouseMetaKey :: IsMouseEvent e => EventM t e Bool mouseMetaKey = event >>= (lift . MouseEvent.getMetaKey) mouseButton :: IsMouseEvent e => EventM t e Word mouseButton = event >>= (lift . MouseEvent.getButton) mouseRelatedTarget :: IsMouseEvent e => EventM t e (Maybe EventTarget) mouseRelatedTarget = event >>= (lift . MouseEvent.getRelatedTarget) mouseOffsetX :: IsMouseEvent e => EventM t e Int mouseOffsetX = event >>= (lift . MouseEvent.getOffsetX) mouseOffsetY :: IsMouseEvent e => EventM t e Int mouseOffsetY = event >>= (lift . MouseEvent.getOffsetY) mouseOffsetXY :: IsMouseEvent e => EventM t e (Int, Int) mouseOffsetXY = do e <- event x <- lift $ MouseEvent.getOffsetX e y <- lift $ MouseEvent.getOffsetY e return (x, y) mouseX :: IsMouseEvent e => EventM t e Int mouseX = event >>= (lift . MouseEvent.getX) mouseY :: IsMouseEvent e => EventM t e Int mouseY = event >>= (lift . MouseEvent.getY) mouseXY :: IsMouseEvent e => EventM t e (Int, Int) mouseXY = do e <- event x <- lift $ MouseEvent.getX e y <- lift $ MouseEvent.getY e return (x, y) mouseFromElement :: IsMouseEvent e => EventM t e (Maybe Node) mouseFromElement = event >>= (lift . MouseEvent.getFromElement) mouseToElement :: IsMouseEvent e => EventM t e (Maybe Node) mouseToElement = event >>= (lift . MouseEvent.getToElement)