@@ -1,3 +1,4 @@
1{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE EmptyDataDecls #-}
4{-# LANGUAGE EmptyDataDecls #-}
@@ -11,7 +12,9 @@
11{-# LANGUAGE RankNTypes #-}
12{-# LANGUAGE RankNTypes #-}
12{-# LANGUAGE RecursiveDo #-}
13{-# LANGUAGE RecursiveDo #-}
13{-# LANGUAGE ScopedTypeVariables #-}
14{-# LANGUAGE ScopedTypeVariables #-}
15+#ifdef USE_TEMPLATE_HASKELL
14{-# LANGUAGE TemplateHaskell #-}
16{-# LANGUAGE TemplateHaskell #-}
15{-# LANGUAGE TypeFamilies #-}
18{-# LANGUAGE TypeFamilies #-}
16{-# LANGUAGE TypeOperators #-}
19{-# LANGUAGE TypeOperators #-}
17{-# LANGUAGE UndecidableInstances #-}
20{-# LANGUAGE UndecidableInstances #-}
@@ -34,6 +37,9 @@ import Control.Monad.Primitive
34import Control.Monad.Reader
37import Control.Monad.Reader
35import Control.Monad.Ref
38import Control.Monad.Ref
36import Control.Monad.Trans.Control
39import Control.Monad.Trans.Control
40+#ifndef USE_TEMPLATE_HASKELL
41+import Data.Functor.Contravariant (phantom)
37import Data.Bitraversable
43import Data.Bitraversable
38import Data.Default
44import Data.Default
39import Data.Dependent.Map (DMap)
45import Data.Dependent.Map (DMap)
@@ -48,7 +54,7 @@ import Data.Monoid
48import Data.Some (Some)
54import Data.Some (Some)
49import qualified Data.Some as Some
55import qualified Data.Some as Some
50import Data.Text (Text)
56import Data.Text (Text)
51−import GHCJS.DOM.Document (Document, createDocumentFragment, createElement, createElementNS, createTextNode)
57+import GHCJS.DOM.Document (Document, createDocumentFragmentUnchecked, createElementUnchecked, createElementNSUnchecked, createTextNodeUnchecked)
52import GHCJS.DOM.Element (getScrollTop, removeAttribute, removeAttributeNS, setAttribute, setAttributeNS)
58import GHCJS.DOM.Element (getScrollTop, removeAttribute, removeAttributeNS, setAttribute, setAttributeNS)
53import qualified GHCJS.DOM.Element as Element
59import qualified GHCJS.DOM.Element as Element
54import qualified GHCJS.DOM.Event as Event
60import qualified GHCJS.DOM.Event as Event
@@ -59,15 +65,17 @@ import qualified GHCJS.DOM.HTMLInputElement as Input
59import qualified GHCJS.DOM.HTMLSelectElement as Select
65import qualified GHCJS.DOM.HTMLSelectElement as Select
60import qualified GHCJS.DOM.HTMLTextAreaElement as TextArea
66import qualified GHCJS.DOM.HTMLTextAreaElement as TextArea
61import GHCJS.DOM.MouseEvent
67import GHCJS.DOM.MouseEvent
62−import GHCJS.DOM.Node (appendChild, getOwnerDocument, getParentNode, getPreviousSibling, removeChild,
68+import GHCJS.DOM.Node (appendChild_, getOwnerDocumentUnchecked, getParentNodeUnchecked,
63 setNodeValue, toNode)
69 setNodeValue, toNode)
64−import qualified GHCJS.DOM.Node as DOM
70+import qualified GHCJS.DOM.Node as DOM (insertBefore_)
71+import GHCJS.DOM.Types
72+ (liftJSM, askJSM, runJSM, JSM, MonadJSM(..),
65−import GHCJS.DOM.Types (FocusEvent, IsElement, IsEvent, IsNode, KeyboardEvent, Node, ToDOMString, TouchEvent,
73+ FocusEvent, IsElement, IsEvent, IsNode, KeyboardEvent, Node,
66− WheelEvent, castToHTMLInputElement, castToHTMLSelectElement,
74+ ToDOMString, TouchEvent, WheelEvent, uncheckedCastTo)
67− castToHTMLTextAreaElement)
68import qualified GHCJS.DOM.Types as DOM
75import qualified GHCJS.DOM.Types as DOM
69import GHCJS.DOM.UIEvent
76import GHCJS.DOM.UIEvent
70import qualified GHCJS.DOM.Window as Window
77import qualified GHCJS.DOM.Window as Window
78+import Language.Javascript.JSaddle (call, eval)
72import Debug.Trace hiding (traceEvent)
80import Debug.Trace hiding (traceEvent)
@@ -81,6 +89,11 @@ data ImmediateDomBuilderEnv t
82newtype ImmediateDomBuilderT t m a = ImmediateDomBuilderT { unImmediateDomBuilderT :: ReaderT (ImmediateDomBuilderEnv t) m a } deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException, MonadAsyncException)
90newtype ImmediateDomBuilderT t m a = ImmediateDomBuilderT { unImmediateDomBuilderT :: ReaderT (ImmediateDomBuilderEnv t) m a } deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException, MonadAsyncException)
93+instance MonadJSM m => MonadJSM (ImmediateDomBuilderT t m) where
94+ liftJSM' = ImmediateDomBuilderT . liftJSM'
84instance PrimMonad m => PrimMonad (ImmediateDomBuilderT x m) where
97instance PrimMonad m => PrimMonad (ImmediateDomBuilderT x m) where
85 type PrimState (ImmediateDomBuilderT x m) = PrimState m
98 type PrimState (ImmediateDomBuilderT x m) = PrimState m
86 primitive = lift . primitive
99 primitive = lift . primitive
@@ -110,64 +123,81 @@ askEvents :: Monad m => ImmediateDomBuilderT t m (Chan [DSum (TriggerRef t) Trig
110askEvents = ImmediateDomBuilderT $ asks _immediateDomBuilderEnv_events
123askEvents = ImmediateDomBuilderT $ asks _immediateDomBuilderEnv_events
112{-# INLINABLE append #-}
125{-# INLINABLE append #-}
113−append :: (IsNode n, MonadIO m) => n -> ImmediateDomBuilderT t m ()
126+append :: (IsNode n, MonadJSM m) => n -> ImmediateDomBuilderT t m ()
114append n = do
127append n = do
115 p <- askParent
128 p <- askParent
116− _ <- liftIO $ appendChild p $ Just n
129+ liftJSM $ appendChild_ p $ Just n
117 return ()
130 return ()
119{-# INLINABLE textNodeInternal #-}
132{-# INLINABLE textNodeInternal #-}
120−textNodeInternal :: (MonadIO m, ToDOMString contents) => contents -> ImmediateDomBuilderT t m DOM.Text
133+textNodeInternal :: (MonadJSM m, ToDOMString contents) => contents -> ImmediateDomBuilderT t m DOM.Text
121textNodeInternal t = do
134textNodeInternal t = do
122 doc <- askDocument
135 doc <- askDocument
123− Just n <- liftIO $ createTextNode doc t
136+ n <- liftJSM $ createTextNodeUnchecked doc t
127−-- | s and e must both be children of the same node and s must precede e
140+-- | s and e must both be children of the same node and s must precede e;
141+-- s, e and all nodes between s and e will be removed
128{-# INLINABLE deleteBetweenInclusive #-}
142{-# INLINABLE deleteBetweenInclusive #-}
129−deleteBetweenInclusive :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
143+deleteBetweenInclusive :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m ()
130−deleteBetweenInclusive s e = do
144+deleteBetweenInclusive s e = liftJSM $ do
131− mCurrentParent <- getParentNode e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
145+ f <- eval ("(function(s,e){ \
132− case mCurrentParent of
146+ p = e.parentNode; \
133− Nothing -> return () --TODO: Is this the right behavior?
147+ if(p !== null) { \
134− Just currentParent -> do
148+ for(;;){ \
135− deleteUpToGivenParent currentParent s e
149+ x = e.previousSibling; \
136− _ <- removeChild currentParent $ Just e
150+ p.removeChild(x); \
137− return ()
151+ if(s===x) break; \
155+ void $ call f f (s, e)
139−-- | s and e must both be children of the same node and s must precede e
157+-- | s and e must both be children of the same node and s must precede e;
158+-- all nodes between s and e will be removed, but s and e will not be removed
140−deleteBetweenExclusive :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
159+deleteBetweenExclusive :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m ()
141−deleteBetweenExclusive s e = do
160+deleteBetweenExclusive s e = liftJSM $ do
142− mCurrentParent <- getParentNode e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
161+ f <- eval ("(function(s,e){ \
143− case mCurrentParent of
162+ p = e.parentNode; \
144− Nothing -> return () --TODO: Is this the right behavior?
163+ if(p !== null) { \
145− Just currentParent -> do
164+ for(;;){ \
146− let go = do
165+ x = e.previousSibling; \
147− Just x <- getPreviousSibling e -- This can't be Nothing because we should hit 's' first
166+ if(s===x) break; \
148− when (toNode s /= toNode x) $ do
167+ p.removeChild(x); \
149− _ <- removeChild currentParent $ Just x
168+ } \
150− go
169+ }})" :: Text)
151− go
170+ void $ call f f (s, e)
172+-- | s and e must both be children of the same node and s must precede e;
153−-- | s and e must both be children of the same node and s must precede e; s and all nodes between s and e will be removed, but e will not be removed
173+-- s and all nodes between s and e will be removed, but e will not be removed
154{-# INLINABLE deleteUpTo #-}
174{-# INLINABLE deleteUpTo #-}
155−deleteUpTo :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
175+deleteUpTo :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m ()
156−deleteUpTo s e = do
176+deleteUpTo s e = liftJSM $ do
157− mCurrentParent <- getParentNode e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
177+ f <- eval ("(function(s,e){ \
158− case mCurrentParent of
178+ p = e.parentNode; \
159− Nothing -> return () --TODO: Is this the right behavior?
179+ if(p !== null) { \
160− Just currentParent -> deleteUpToGivenParent currentParent s e
180+ for(;;) { \
161−
181+ x = e.previousSibling; \
186+ void $ call f f (s, e)
188+-- | s and all nodes between s and e will be removed, but e will not be removed
162{-# INLINABLE deleteUpToGivenParent #-}
189{-# INLINABLE deleteUpToGivenParent #-}
163−deleteUpToGivenParent :: (MonadIO m, IsNode parent, IsNode start, IsNode end) => parent -> start -> end -> m ()
190+deleteUpToGivenParent :: (MonadJSM m, IsNode parent, IsNode start, IsNode end) => parent -> start -> end -> m ()
164−deleteUpToGivenParent currentParent s e = do
191+deleteUpToGivenParent currentParent s e = liftJSM $ do
165− fix $ \loop -> do
192+ f <- eval ("(function(p,s,e){ \
166− Just x <- getPreviousSibling e -- This can't be Nothing because we should hit 's' first
193+ for(;;){ \
194+ x = e.previousSibling; \
167− _ <- removeChild currentParent $ Just x
195+ p.removeChild(x); \
168− when (toNode s /= toNode x) loop
196+ if(s===x) break; \
198+ void $ call f f (currentParent, s, e)
170−type SupportsImmediateDomBuilder t m = (Reflex t, MonadIO m, MonadIO (Performable m), MonadHold t m, MonadFix m, PerformEvent t m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref IO, MonadAdjust t m)
200+type SupportsImmediateDomBuilder t m = (Reflex t, MonadJSM m, MonadJSM (Performable m), MonadHold t m, MonadFix m, PerformEvent t m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref JSM, MonadAdjust t m)
172newtype EventFilterTriggerRef t er (en :: EventTag) = EventFilterTriggerRef (IORef (Maybe (EventTrigger t (er en))))
202newtype EventFilterTriggerRef t er (en :: EventTag) = EventFilterTriggerRef (IORef (Maybe (EventTrigger t (er en))))
@@ -177,35 +207,37 @@ wrap e cfg = do
177 lift $ performEvent_ $ ffor (cfg ^. modifyAttributes) $ imapM_ $ \(AttributeName mAttrNamespace n) mv -> case mAttrNamespace of
207 lift $ performEvent_ $ ffor (cfg ^. modifyAttributes) $ imapM_ $ \(AttributeName mAttrNamespace n) mv -> case mAttrNamespace of
178 Nothing -> maybe (removeAttribute e n) (setAttribute e n) mv
208 Nothing -> maybe (removeAttribute e n) (setAttribute e n) mv
179 Just ns -> maybe (removeAttributeNS e (Just ns) n) (setAttributeNS e (Just ns) n) mv
209 Just ns -> maybe (removeAttributeNS e (Just ns) n) (setAttributeNS e (Just ns) n) mv
180− eventTriggerRefs :: DMap EventName (EventFilterTriggerRef t er) <- liftIO $ fmap DMap.fromList $ forM (DMap.toList $ _ghcjsEventSpec_filters $ _rawElementConfig_eventSpec cfg) $ \(en :=> GhcjsEventFilter f) -> do
210+ eventTriggerRefs :: DMap EventName (EventFilterTriggerRef t er) <- liftJSM $ fmap DMap.fromList $ forM (DMap.toList $ _ghcjsEventSpec_filters $ _rawElementConfig_eventSpec cfg) $ \(en :=> GhcjsEventFilter f) -> do
181− triggerRef <- newIORef Nothing
211+ triggerRef <- liftIO $ newIORef Nothing
182 _ <- elementOnEventName en e $ do
212 _ <- elementOnEventName en e $ do
183 evt <- DOM.event
213 evt <- DOM.event
184− (flags, k) <- liftIO $ f $ GhcjsDomEvent evt
214+ (flags, k) <- liftJSM $ f $ GhcjsDomEvent evt
185 when (_eventFlags_preventDefault flags) $ withIsEvent en DOM.preventDefault
215 when (_eventFlags_preventDefault flags) $ withIsEvent en DOM.preventDefault
186 case _eventFlags_propagation flags of
216 case _eventFlags_propagation flags of
187 Propagation_Continue -> return ()
217 Propagation_Continue -> return ()
188 Propagation_Stop -> withIsEvent en DOM.stopPropagation
218 Propagation_Stop -> withIsEvent en DOM.stopPropagation
189 Propagation_StopImmediate -> withIsEvent en DOM.stopImmediatePropagation
219 Propagation_StopImmediate -> withIsEvent en DOM.stopImmediatePropagation
190− mv <- liftIO k --TODO: Only do this when the event is subscribed
220+ mv <- liftJSM k --TODO: Only do this when the event is subscribed
191 liftIO $ forM_ mv $ \v -> writeChan events [TriggerRef triggerRef :=> TriggerInvocation v (return ())]
221 liftIO $ forM_ mv $ \v -> writeChan events [TriggerRef triggerRef :=> TriggerInvocation v (return ())]
192 return $ en :=> EventFilterTriggerRef triggerRef
222 return $ en :=> EventFilterTriggerRef triggerRef
193− es <- newFanEventWithTrigger $ \(WrapArg en) t -> do
225+ newFanEventWithTrigger $ \(WrapArg en) t ->
194− case DMap.lookup en eventTriggerRefs of
226+ case DMap.lookup en eventTriggerRefs of
195− Just (EventFilterTriggerRef r) -> do
227+ Just (EventFilterTriggerRef r) -> do
196− writeIORef r $ Just t
228+ writeIORef r $ Just t
197− return $ do
229+ return $ do
198− writeIORef r Nothing
230+ writeIORef r Nothing
199− Nothing -> elementOnEventName en e $ do
231+ Nothing -> (`runJSM` ctx) <$> (`runJSM` ctx) (elementOnEventName en e $ do
200− evt <- DOM.event
232+ evt <- DOM.event
201− let h = _ghcjsEventSpec_handler $ _rawElementConfig_eventSpec cfg
233+ let h = _ghcjsEventSpec_handler $ _rawElementConfig_eventSpec cfg
202− mv <- liftIO $ h (en, GhcjsDomEvent evt)
234+ mv <- lift $ h (en, GhcjsDomEvent evt)
203− case mv of
235+ case mv of
204− Nothing -> return ()
236+ Nothing -> return ()
205− Just v -> liftIO $ do
237+ Just v -> liftIO $ do
206− --TODO: I don't think this is quite right: if a new trigger is created between when this is enqueued and when it fires, this may not work quite right
238+ --TODO: I don't think this is quite right: if a new trigger is created between when this is enqueued and when it fires, this may not work quite right
207− ref <- newIORef $ Just t
239+ ref <- newIORef $ Just t
208− writeChan events [TriggerRef ref :=> TriggerInvocation v (return ())]
240+ writeChan events [TriggerRef ref :=> TriggerInvocation v (return ())])
209 return $ Element es e
241 return $ Element es e
211{-# INLINABLE makeElement #-}
243{-# INLINABLE makeElement #-}
@@ -213,12 +245,12 @@ makeElement :: forall er t m a. SupportsImmediateDomBuilder t m => Text -> Eleme
213makeElement elementTag cfg child = do
245makeElement elementTag cfg child = do
214 doc <- askDocument
246 doc <- askDocument
215 events <- askEvents
247 events <- askEvents
216− Just e <- ImmediateDomBuilderT $ fmap DOM.castToElement <$> case cfg ^. namespace of
248+ e <- liftJSM $ case cfg ^. namespace of
217− Nothing -> createElement doc (Just elementTag)
249+ Nothing -> createElementUnchecked doc (Just elementTag)
218− Just ens -> createElementNS doc (Just ens) (Just elementTag)
250+ Just ens -> createElementNSUnchecked doc (Just ens) (Just elementTag)
219 ImmediateDomBuilderT $ iforM_ (cfg ^. initialAttributes) $ \(AttributeName mAttrNamespace n) v -> case mAttrNamespace of
251 ImmediateDomBuilderT $ iforM_ (cfg ^. initialAttributes) $ \(AttributeName mAttrNamespace n) v -> case mAttrNamespace of
220− Nothing -> setAttribute e n v
252+ Nothing -> lift $ setAttribute e n v
221− Just ans -> setAttributeNS e (Just ans) n v
253+ Just ans -> lift $ setAttributeNS e (Just ans) n v
222 result <- lift $ runImmediateDomBuilderT child $ ImmediateDomBuilderEnv
254 result <- lift $ runImmediateDomBuilderT child $ ImmediateDomBuilderEnv
223 { _immediateDomBuilderEnv_parent = toNode e
255 { _immediateDomBuilderEnv_parent = toNode e
224 , _immediateDomBuilderEnv_document = doc
256 , _immediateDomBuilderEnv_document = doc
@@ -228,9 +260,9 @@ makeElement elementTag cfg child = do
228 wrapped <- wrap e $ extractRawElementConfig cfg
260 wrapped <- wrap e $ extractRawElementConfig cfg
229 return ((wrapped, result), e)
261 return ((wrapped, result), e)
231−newtype GhcjsDomHandler a b = GhcjsDomHandler { unGhcjsDomHandler :: a -> IO b }
263+newtype GhcjsDomHandler a b = GhcjsDomHandler { unGhcjsDomHandler :: a -> JSM b }
233−newtype GhcjsDomHandler1 a b = GhcjsDomHandler1 { unGhcjsDomHandler1 :: forall (x :: EventTag). a x -> IO (b x) }
265+newtype GhcjsDomHandler1 a b = GhcjsDomHandler1 { unGhcjsDomHandler1 :: forall (x :: EventTag). a x -> JSM (b x) }
235newtype GhcjsDomEvent en = GhcjsDomEvent { unGhcjsDomEvent :: EventType en }
267newtype GhcjsDomEvent en = GhcjsDomEvent { unGhcjsDomEvent :: EventType en }
@@ -258,7 +290,7 @@ instance DomSpace GhcjsDomSpace where
258 in DMap.alter f' en $ _ghcjsEventSpec_filters es
290 in DMap.alter f' en $ _ghcjsEventSpec_filters es
261−newtype GhcjsEventFilter er en = GhcjsEventFilter (GhcjsDomEvent en -> IO (EventFlags, IO (Maybe (er en))))
293+newtype GhcjsEventFilter er en = GhcjsEventFilter (GhcjsDomEvent en -> JSM (EventFlags, JSM (Maybe (er en))))
263data Pair1 (f :: k -> *) (g :: k -> *) (a :: k) = Pair1 (f a) (g a)
295data Pair1 (f :: k -> *) (g :: k -> *) (a :: k) = Pair1 (f a) (g a)
@@ -266,15 +298,29 @@ data Maybe1 f a = Nothing1 | Just1 (f a)
267data GhcjsEventSpec er = GhcjsEventSpec
299data GhcjsEventSpec er = GhcjsEventSpec
268 { _ghcjsEventSpec_filters :: DMap EventName (GhcjsEventFilter er)
300 { _ghcjsEventSpec_filters :: DMap EventName (GhcjsEventFilter er)
269− , _ghcjsEventSpec_handler :: forall en. (EventName en, GhcjsDomEvent en) -> IO (Maybe (er en))
301+ , _ghcjsEventSpec_handler :: forall en. (EventName en, GhcjsDomEvent en) -> JSM (Maybe (er en))
304+#ifndef USE_TEMPLATE_HASKELL
305+phantom2 :: (Functor f, Contravariant f) => f a -> f b
307+{-# INLINE phantom2 #-}
309+ghcjsEventSpec_filters :: forall er . Lens' (GhcjsEventSpec er) (DMap EventName (GhcjsEventFilter er))
310+ghcjsEventSpec_filters f (GhcjsEventSpec a b) = (\a' -> GhcjsEventSpec a' b) <$> f a
311+{-# INLINE ghcjsEventSpec_filters #-}
312+ghcjsEventSpec_handler :: forall er en . Getter (GhcjsEventSpec er) ((EventName en, GhcjsDomEvent en) -> JSM (Maybe (er en)))
313+ghcjsEventSpec_handler f (GhcjsEventSpec _ b) = phantom2 (f b)
314+{-# INLINE ghcjsEventSpec_handler #-}
272instance er ~ EventResult => Default (GhcjsEventSpec er) where
317instance er ~ EventResult => Default (GhcjsEventSpec er) where
273 def = GhcjsEventSpec
318 def = GhcjsEventSpec
274 { _ghcjsEventSpec_filters = mempty
319 { _ghcjsEventSpec_filters = mempty
275 , _ghcjsEventSpec_handler = \(en, GhcjsDomEvent evt) -> do
320 , _ghcjsEventSpec_handler = \(en, GhcjsDomEvent evt) -> do
276− Just t <- withIsEvent en $ Event.getTarget evt --TODO: Rework this; defaultDomEventHandler shouldn't need to take this as an argument
321+ t :: DOM.EventTarget <- withIsEvent en $ Event.getTargetUnchecked evt --TODO: Rework this; defaultDomEventHandler shouldn't need to take this as an argument
277− runReaderT (defaultDomEventHandler (Element.castToElement t) en) evt
322+ let e = uncheckedCastTo DOM.Element t
323+ runReaderT (defaultDomEventHandler e en) evt
280instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t m) where
326instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t m) where
@@ -300,9 +346,9 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
300 {-# INLINABLE inputElement #-}
346 {-# INLINABLE inputElement #-}
301 inputElement cfg = do
347 inputElement cfg = do
302 ((e, _), domElement) <- makeElement "input" (cfg ^. inputElementConfig_elementConfig) $ return ()
348 ((e, _), domElement) <- makeElement "input" (cfg ^. inputElementConfig_elementConfig) $ return ()
303− let domInputElement = castToHTMLInputElement domElement
349+ let domInputElement = uncheckedCastTo DOM.HTMLInputElement domElement
304 Input.setValue domInputElement $ Just (cfg ^. inputElementConfig_initialValue)
350 Input.setValue domInputElement $ Just (cfg ^. inputElementConfig_initialValue)
305− Just v0 <- Input.getValue domInputElement
351+ v0 <- Input.getValueUnchecked domInputElement
306 let getMyValue = fromMaybe "" <$> Input.getValue domInputElement
352 let getMyValue = fromMaybe "" <$> Input.getValue domInputElement
307 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
353 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
308 valueChangedBySetValue <- performEvent $ ffor (cfg ^. inputElementConfig_setValue) $ \v' -> do
354 valueChangedBySetValue <- performEvent $ ffor (cfg ^. inputElementConfig_setValue) $ \v' -> do
@@ -317,10 +363,10 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
317 Input.getChecked domInputElement
363 Input.getChecked domInputElement
318 checkedChangedBySetChecked <- performEvent $ ffor (_inputElementConfig_setChecked cfg) $ \newChecked -> do
364 checkedChangedBySetChecked <- performEvent $ ffor (_inputElementConfig_setChecked cfg) $ \newChecked -> do
319 oldChecked <- Input.getChecked domInputElement
365 oldChecked <- Input.getChecked domInputElement
320− if newChecked /= oldChecked
321− then do Input.setChecked domInputElement newChecked
366+ Input.setChecked domInputElement newChecked
367+ return $ if newChecked /= oldChecked
322− return $ Just newChecked
368+ then Just newChecked
323− else return Nothing
369+ else Nothing
324 c <- holdDyn (_inputElementConfig_initialChecked cfg) $ leftmost
370 c <- holdDyn (_inputElementConfig_initialChecked cfg) $ leftmost
325 [ fmapMaybe id checkedChangedBySetChecked
371 [ fmapMaybe id checkedChangedBySetChecked
326 , checkedChangedByUI
372 , checkedChangedByUI
@@ -347,9 +393,9 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
347 {-# INLINABLE textAreaElement #-}
393 {-# INLINABLE textAreaElement #-}
348 textAreaElement cfg = do --TODO
394 textAreaElement cfg = do --TODO
349 ((e, _), domElement) <- makeElement "textarea" (cfg ^. textAreaElementConfig_elementConfig) $ return ()
395 ((e, _), domElement) <- makeElement "textarea" (cfg ^. textAreaElementConfig_elementConfig) $ return ()
350− let domTextAreaElement = castToHTMLTextAreaElement domElement
396+ let domTextAreaElement = uncheckedCastTo DOM.HTMLTextAreaElement domElement
351 TextArea.setValue domTextAreaElement $ Just (cfg ^. textAreaElementConfig_initialValue)
397 TextArea.setValue domTextAreaElement $ Just (cfg ^. textAreaElementConfig_initialValue)
352− Just v0 <- TextArea.getValue domTextAreaElement
398+ v0 <- TextArea.getValueUnchecked domTextAreaElement
353 let getMyValue = fromMaybe "" <$> TextArea.getValue domTextAreaElement
399 let getMyValue = fromMaybe "" <$> TextArea.getValue domTextAreaElement
354 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
400 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
355 valueChangedBySetValue <- performEvent $ ffor (cfg ^. textAreaElementConfig_setValue) $ \v' -> do
401 valueChangedBySetValue <- performEvent $ ffor (cfg ^. textAreaElementConfig_setValue) $ \v' -> do
@@ -370,7 +416,7 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
370 {-# INLINABLE selectElement #-}
416 {-# INLINABLE selectElement #-}
371 selectElement cfg child = do
417 selectElement cfg child = do
372 ((e, result), domElement) <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
418 ((e, result), domElement) <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
373− let domSelectElement = castToHTMLSelectElement domElement
419+ let domSelectElement = uncheckedCastTo DOM.HTMLSelectElement domElement
374 Select.setValue domSelectElement $ Just (cfg ^. selectElementConfig_initialValue)
420 Select.setValue domSelectElement $ Just (cfg ^. selectElementConfig_initialValue)
375 Just v0 <- Select.getValue domSelectElement
421 Just v0 <- Select.getValue domSelectElement
376 let getMyValue = fromMaybe "" <$> Select.getValue domSelectElement
422 let getMyValue = fromMaybe "" <$> Select.getValue domSelectElement
@@ -394,18 +440,18 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
394 placeRawElement = append
440 placeRawElement = append
395 wrapRawElement = wrap
441 wrapRawElement = wrap
397−instance (Reflex t, MonadAdjust t m, MonadIO m, MonadHold t m, PerformEvent t m, MonadIO (Performable m)) => MonadAdjust t (ImmediateDomBuilderT t m) where
443+instance (Reflex t, MonadAdjust t m, MonadJSM m, MonadHold t m, PerformEvent t m, MonadJSM (Performable m)) => MonadAdjust t (ImmediateDomBuilderT t m) where
398 runWithReplace a0 a' = do
444 runWithReplace a0 a' = do
399 initialEnv <- ImmediateDomBuilderT ask
445 initialEnv <- ImmediateDomBuilderT ask
400 before <- textNodeInternal ("" :: Text)
446 before <- textNodeInternal ("" :: Text)
401 -- We draw 'after' in this roundabout way to avoid using MonadFix
447 -- We draw 'after' in this roundabout way to avoid using MonadFix
402− Just after <- createTextNode (_immediateDomBuilderEnv_document initialEnv) ("" :: Text)
448+ after <- createTextNodeUnchecked (_immediateDomBuilderEnv_document initialEnv) ("" :: Text)
403 let drawInitialChild = do
449 let drawInitialChild = do
404 result <- a0
450 result <- a0
405 append after
451 append after
406 return result
452 return result
407 (result0, result') <- lift $ runWithReplace (runImmediateDomBuilderT drawInitialChild initialEnv) $ ffor a' $ \child -> do
453 (result0, result') <- lift $ runWithReplace (runImmediateDomBuilderT drawInitialChild initialEnv) $ ffor a' $ \child -> do
408− Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
454+ df <- createDocumentFragmentUnchecked $ _immediateDomBuilderEnv_document initialEnv
409 result <- runImmediateDomBuilderT child $ initialEnv
455 result <- runImmediateDomBuilderT child $ initialEnv
410 { _immediateDomBuilderEnv_parent = toNode df
456 { _immediateDomBuilderEnv_parent = toNode df
@@ -419,7 +465,7 @@ instance (Reflex t, MonadAdjust t m, MonadIO m, MonadHold t m, PerformEvent t m,
419 drawChildInitial child = runImmediateDomBuilderT ((,,) <$> pure (error "sequenceDMapWithAdjust{ImmediateDomBuilderT}: drawChildInitial: DocumentFragment evaluated") <*> textNodeInternal ("" :: Text) <*> child) initialEnv --TODO: Don't return a DocumentFragment at all here; this will require that sequenceDMapWithAdjust accept differently-typed values for the constant and Event arguments.
465 drawChildInitial child = runImmediateDomBuilderT ((,,) <$> pure (error "sequenceDMapWithAdjust{ImmediateDomBuilderT}: drawChildInitial: DocumentFragment evaluated") <*> textNodeInternal ("" :: Text) <*> child) initialEnv --TODO: Don't return a DocumentFragment at all here; this will require that sequenceDMapWithAdjust accept differently-typed values for the constant and Event arguments.
420 drawChildUpdate :: ImmediateDomBuilderT t m a -> m (DOM.DocumentFragment, DOM.Text, a)
466 drawChildUpdate :: ImmediateDomBuilderT t m a -> m (DOM.DocumentFragment, DOM.Text, a)
421 drawChildUpdate child = do
467 drawChildUpdate child = do
422− Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
468+ df <- createDocumentFragmentUnchecked $ _immediateDomBuilderEnv_document initialEnv
423 runImmediateDomBuilderT ((,,) <$> pure df <*> textNodeInternal ("" :: Text) <*> child) $ initialEnv
469 runImmediateDomBuilderT ((,,) <$> pure df <*> textNodeInternal ("" :: Text) <*> child) $ initialEnv
424 { _immediateDomBuilderEnv_parent = toNode df
470 { _immediateDomBuilderEnv_parent = toNode df
@@ -454,12 +500,12 @@ mkHasFocus e = do
456{-# INLINABLE insertImmediateAbove #-}
502{-# INLINABLE insertImmediateAbove #-}
457−insertImmediateAbove :: (IsNode placeholder, PerformEvent t m, MonadIO (Performable m)) => placeholder -> Event t (ImmediateDomBuilderT t (Performable m) a) -> ImmediateDomBuilderT t m (Event t a)
503+insertImmediateAbove :: (IsNode placeholder, PerformEvent t m, MonadJSM (Performable m)) => placeholder -> Event t (ImmediateDomBuilderT t (Performable m) a) -> ImmediateDomBuilderT t m (Event t a)
458insertImmediateAbove n toInsertAbove = do
504insertImmediateAbove n toInsertAbove = do
459 events <- askEvents
505 events <- askEvents
460 lift $ performEvent $ ffor toInsertAbove $ \new -> do
506 lift $ performEvent $ ffor toInsertAbove $ \new -> do
461− Just doc <- getOwnerDocument n
507+ doc <- getOwnerDocumentUnchecked n
462− Just df <- createDocumentFragment doc
508+ df <- createDocumentFragmentUnchecked doc
463 result <- runImmediateDomBuilderT new $ ImmediateDomBuilderEnv
509 result <- runImmediateDomBuilderT new $ ImmediateDomBuilderEnv
464 { _immediateDomBuilderEnv_parent = toNode df
510 { _immediateDomBuilderEnv_parent = toNode df
465 , _immediateDomBuilderEnv_document = doc
511 , _immediateDomBuilderEnv_document = doc
@@ -468,12 +514,10 @@ insertImmediateAbove n toInsertAbove = do
468 df `insertBefore` n
514 df `insertBefore` n
469 return result
515 return result
471−insertBefore :: (MonadIO m, IsNode new, IsNode existing) => new -> existing -> m ()
517+insertBefore :: (MonadJSM m, IsNode new, IsNode existing) => new -> existing -> m ()
472insertBefore new existing = do
518insertBefore new existing = do
473− mp <- getParentNode existing
519+ p <- getParentNodeUnchecked existing
475− Nothing -> trace "ImmediateDomBuilderT: placeholder: Warning: (getParentNode n) returned Nothing" $ return ()
476− Just p -> void $ DOM.insertBefore p (Just new) (Just existing) -- If there's no parent, that means we've been removed from the DOM; this should not happen if the we're removing ourselves from the performEvent properly
520+ DOM.insertBefore_ p (Just new) (Just existing) -- If there's no parent, that means we've been removed from the DOM; this should not happen if the we're removing ourselves from the performEvent properly
478instance PerformEvent t m => PerformEvent t (ImmediateDomBuilderT t m) where
522instance PerformEvent t m => PerformEvent t (ImmediateDomBuilderT t m) where
479 type Performable (ImmediateDomBuilderT t m) = Performable m
523 type Performable (ImmediateDomBuilderT t m) = Performable m
@@ -501,17 +545,17 @@ instance (Monad m, MonadRef m, Ref m ~ Ref IO, MonadReflexCreateTrigger t m) =>
501 newTriggerEventWithOnComplete = do
545 newTriggerEventWithOnComplete = do
502 events <- askEvents
546 events <- askEvents
503 (eResult, reResultTrigger) <- lift newEventWithTriggerRef
547 (eResult, reResultTrigger) <- lift newEventWithTriggerRef
504− return $ (,) eResult $ \a cb -> writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a cb]
548+ return $ (,) eResult $ \a cb -> writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a (liftIO cb)]
505 {-# INLINABLE newEventWithLazyTriggerWithOnComplete #-}
549 {-# INLINABLE newEventWithLazyTriggerWithOnComplete #-}
506 newEventWithLazyTriggerWithOnComplete f = do
550 newEventWithLazyTriggerWithOnComplete f = do
507 events <- askEvents
551 events <- askEvents
508 lift $ newEventWithTrigger $ \t -> f $ \a cb -> do
552 lift $ newEventWithTrigger $ \t -> f $ \a cb -> do
509 reResultTrigger <- newIORef $ Just t
553 reResultTrigger <- newIORef $ Just t
510− writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a cb]
554+ writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a (liftIO cb)]
512−instance HasWebView m => HasWebView (ImmediateDomBuilderT t m) where
556+instance HasJSContext m => HasJSContext (ImmediateDomBuilderT t m) where
513− type WebViewPhantom (ImmediateDomBuilderT t m) = WebViewPhantom m
557+ type JSContextPhantom (ImmediateDomBuilderT t m) = JSContextPhantom m
514− askWebView = lift askWebView
558+ askJSContext = lift askJSContext
516instance MonadRef m => MonadRef (ImmediateDomBuilderT t m) where
560instance MonadRef m => MonadRef (ImmediateDomBuilderT t m) where
517 type Ref (ImmediateDomBuilderT t m) = Ref m
561 type Ref (ImmediateDomBuilderT t m) = Ref m
@@ -527,7 +571,7 @@ instance MonadAtomicRef m => MonadAtomicRef (ImmediateDomBuilderT t m) where
527 atomicModifyRef r = lift . atomicModifyRef r
571 atomicModifyRef r = lift . atomicModifyRef r
529instance (HasJS x m, ReflexHost t) => HasJS x (ImmediateDomBuilderT t m) where
573instance (HasJS x m, ReflexHost t) => HasJS x (ImmediateDomBuilderT t m) where
530− type JSM (ImmediateDomBuilderT t m) = JSM m
574+ type JSX (ImmediateDomBuilderT t m) = JSX m
531 liftJS = lift . liftJS
575 liftJS = lift . liftJS
533type family EventType en where
577type family EventType en where
@@ -728,8 +772,57 @@ withIsEvent en r = case en of
728 Mousewheel -> r
772 Mousewheel -> r
729 Wheel -> r
773 Wheel -> r
775+showEventName :: EventName en -> String
776+showEventName en = case en of
781+ Contextmenu -> "Contextmenu"
782+ Dblclick -> "Dblclick"
784+ Dragend -> "Dragend"
785+ Dragenter -> "Dragenter"
786+ Dragleave -> "Dragleave"
787+ Dragover -> "Dragover"
788+ Dragstart -> "Dragstart"
793+ Invalid -> "Invalid"
794+ Keydown -> "Keydown"
795+ Keypress -> "Keypress"
798+ Mousedown -> "Mousedown"
799+ Mouseenter -> "Mouseenter"
800+ Mouseleave -> "Mouseleave"
801+ Mousemove -> "Mousemove"
802+ Mouseout -> "Mouseout"
803+ Mouseover -> "Mouseover"
804+ Mouseup -> "Mouseup"
805+ Mousewheel -> "Mousewheel"
810+ Beforecut -> "Beforecut"
812+ Beforecopy -> "Beforecopy"
814+ Beforepaste -> "Beforepaste"
818+ Selectstart -> "Selectstart"
819+ Touchstart -> "Touchstart"
820+ Touchmove -> "Touchmove"
821+ Touchend -> "Touchend"
822+ Touchcancel -> "Touchcancel"
731{-# INLINABLE elementOnEventName #-}
824{-# INLINABLE elementOnEventName #-}
732−elementOnEventName :: IsElement e => EventName en -> e -> EventM e (EventType en) () -> IO (IO ())
825+elementOnEventName :: IsElement e => EventName en -> e -> EventM e (EventType en) () -> JSM (JSM ())
733elementOnEventName en e = case en of
826elementOnEventName en e = case en of
734 Abort -> on e Element.abort
827 Abort -> on e Element.abort
735 Blur -> on e Element.blurEvent
828 Blur -> on e Element.blurEvent
@@ -779,7 +872,7 @@ elementOnEventName en e = case en of
779 Touchcancel -> on e Element.touchCancel
872 Touchcancel -> on e Element.touchCancel
781{-# INLINABLE windowOnEventName #-}
874{-# INLINABLE windowOnEventName #-}
782−windowOnEventName :: EventName en -> DOM.Window -> EventM DOM.Window (EventType en) () -> IO (IO ())
875+windowOnEventName :: EventName en -> DOM.Window -> EventM DOM.Window (EventType en) () -> JSM (JSM ())
783windowOnEventName en e = case en of
876windowOnEventName en e = case en of
784 Abort -> on e Window.abort
877 Abort -> on e Window.abort
785 Blur -> on e Window.blurEvent
878 Blur -> on e Window.blurEvent
@@ -829,15 +922,15 @@ windowOnEventName en e = case en of
829 Touchcancel -> on e Window.touchCancel
922 Touchcancel -> on e Window.touchCancel
831{-# INLINABLE wrapDomEvent #-}
924{-# INLINABLE wrapDomEvent #-}
832−wrapDomEvent :: TriggerEvent t m => e -> (e -> EventM e event () -> IO (IO ())) -> EventM e event a -> m (Event t a)
925+wrapDomEvent :: (TriggerEvent t m, MonadJSM m) => e -> (e -> EventM e event () -> JSM (JSM ())) -> EventM e event a -> m (Event t a)
833wrapDomEvent el elementOnevent getValue = wrapDomEventMaybe el elementOnevent $ fmap Just getValue
926wrapDomEvent el elementOnevent getValue = wrapDomEventMaybe el elementOnevent $ fmap Just getValue
835{-# INLINABLE subscribeDomEvent #-}
928{-# INLINABLE subscribeDomEvent #-}
836−subscribeDomEvent :: (EventM e event () -> IO (IO ()))
929+subscribeDomEvent :: (EventM e event () -> JSM (JSM ()))
837 -> EventM e event (Maybe a)
930 -> EventM e event (Maybe a)
838 -> Chan [DSum (TriggerRef t) TriggerInvocation]
931 -> Chan [DSum (TriggerRef t) TriggerInvocation]
839 -> EventTrigger t a
932 -> EventTrigger t a
840− -> IO (IO ())
933+ -> JSM (JSM ())
841subscribeDomEvent elementOnevent getValue eventChan et = elementOnevent $ do
934subscribeDomEvent elementOnevent getValue eventChan et = elementOnevent $ do
842 mv <- getValue
935 mv <- getValue
843 forM_ mv $ \v -> liftIO $ do
936 forM_ mv $ \v -> liftIO $ do
@@ -846,25 +939,28 @@ subscribeDomEvent elementOnevent getValue eventChan et = elementOnevent $ do
846 writeChan eventChan [TriggerRef etr :=> TriggerInvocation v (return ())]
939 writeChan eventChan [TriggerRef etr :=> TriggerInvocation v (return ())]
848{-# INLINABLE wrapDomEventMaybe #-}
941{-# INLINABLE wrapDomEventMaybe #-}
849−wrapDomEventMaybe :: TriggerEvent t m
942+wrapDomEventMaybe :: (TriggerEvent t m, MonadJSM m)
851− -> (e -> EventM e event () -> IO (IO ()))
944+ -> (e -> EventM e event () -> JSM (JSM ()))
852 -> EventM e event (Maybe a)
945 -> EventM e event (Maybe a)
853 -> m (Event t a)
946 -> m (Event t a)
854wrapDomEventMaybe el elementOnevent getValue = do
947wrapDomEventMaybe el elementOnevent getValue = do
855− newEventWithLazyTriggerWithOnComplete $ \trigger -> elementOnevent el $ do
949+ newEventWithLazyTriggerWithOnComplete $ \trigger -> (`runJSM` ctx) <$> (`runJSM` ctx) (elementOnevent el $ do
856 mv <- getValue
950 mv <- getValue
857− forM_ mv $ \v -> liftIO $ trigger v $ return ()
951+ forM_ mv $ \v -> liftIO $ trigger v $ return ())
859{-# INLINABLE wrapDomEventsMaybe #-}
953{-# INLINABLE wrapDomEventsMaybe #-}
860−wrapDomEventsMaybe :: (MonadIO m, MonadReflexCreateTrigger t m)
954+wrapDomEventsMaybe :: (MonadJSM m, MonadReflexCreateTrigger t m)
862 -> (forall en. IsEvent (EventType en) => EventName en -> EventM e (EventType en) (Maybe (f en)))
956 -> (forall en. IsEvent (EventType en) => EventName en -> EventM e (EventType en) (Maybe (f en)))
863− -> (forall en. EventName en -> e -> EventM e (EventType en) () -> IO (IO ()))
957+ -> (forall en. EventName en -> e -> EventM e (EventType en) () -> JSM (JSM ()))
864 -> ImmediateDomBuilderT t m (EventSelector t (WrapArg f EventName))
958 -> ImmediateDomBuilderT t m (EventSelector t (WrapArg f EventName))
865wrapDomEventsMaybe target handlers onEventName = do
959wrapDomEventsMaybe target handlers onEventName = do
866 eventChan <- askEvents
961 eventChan <- askEvents
867− e <- lift $ newFanEventWithTrigger $ \(WrapArg en) -> withIsEvent en $ subscribeDomEvent (onEventName en target) (handlers en) eventChan
962+ e <- lift $ newFanEventWithTrigger $ \(WrapArg en) -> withIsEvent en
963+ (((`runJSM` ctx) <$>) . (`runJSM` ctx) . subscribeDomEvent (onEventName en target) (handlers en) eventChan)
868 return $! e
964 return $! e
870{-# INLINABLE getKeyEvent #-}
966{-# INLINABLE getKeyEvent #-}
@@ -905,7 +1001,7 @@ data Window t = Window
905 , _window_raw :: DOM.Window
1001 , _window_raw :: DOM.Window
908−wrapWindow :: (MonadIO m, MonadReflexCreateTrigger t m) => DOM.Window -> WindowConfig t -> ImmediateDomBuilderT t m (Window t)
1004+wrapWindow :: (MonadJSM m, MonadReflexCreateTrigger t m) => DOM.Window -> WindowConfig t -> ImmediateDomBuilderT t m (Window t)
909wrapWindow wv _ = do
1005wrapWindow wv _ = do
910 events <- wrapDomEventsMaybe wv (defaultDomWindowEventHandler wv) windowOnEventName
1006 events <- wrapDomEventsMaybe wv (defaultDomWindowEventHandler wv) windowOnEventName
911 return $ Window
1007 return $ Window
@@ -913,4 +1009,6 @@ wrapWindow wv _ = do
913 , _window_raw = wv
1009 , _window_raw = wv
1012+#ifdef USE_TEMPLATE_HASKELL
916makeLenses ''GhcjsEventSpec
1013makeLenses ''GhcjsEventSpec