on develop help sign in
Implement runWithReplace; use it to implement widgetHoldInternal
commitd308470eb2ccf1b7f597fe7f43f93b96b4d74a76 authorRyan Trinkle <ryan.trinkle@gmail.com> dateSat 5 Nov 2016, 17:41 (10 years ago) parentb3f0001
6 files changed+41−25
src/Foreign/JavaScript/TH.hs+1 src/Reflex/Dom/Builder/Immediate.hs+32 src/Reflex/Dom/Builder/InputDisabled.hs+1 src/Reflex/Dom/Builder/Static.hs+5 src/Reflex/Dom/Old.hs+1−16 src/Reflex/Dom/Widget/Basic.hs+1−9
src/Foreign/JavaScript/TH.hs+1
@@ -120,6 +120,7 @@ instance PrimMonad m => PrimMonad (WithWebView x m) where
120120 primitive = lift . primitive
121121
122122instance MonadAdjust t m => MonadAdjust t (WithWebView x m) where
123+ runWithReplace a0 a' = WithWebView $ runWithReplace (coerce a0) (coerceEvent a')
123124 sequenceDMapWithAdjust dm0 dm' = WithWebView $ sequenceDMapWithAdjust (coerce dm0) (coerceEvent dm')
124125
125126instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (WithWebView x m) where
src/Reflex/Dom/Builder/Immediate.hs+32
@@ -136,6 +136,20 @@ deleteBetweenInclusive s e = do
136136 _ <- removeChild currentParent $ Just e
137137 return ()
138138
139+-- | s and e must both be children of the same node and s must precede e
140+deleteBetweenExclusive :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
141+deleteBetweenExclusive s e = 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
143+ case mCurrentParent of
144+ Nothing -> return () --TODO: Is this the right behavior?
145+ Just currentParent -> do
146+ let go = do
147+ Just x <- getPreviousSibling e -- This can't be Nothing because we should hit 's' first
148+ when (toNode s /= toNode x) $ do
149+ _ <- removeChild currentParent $ Just x
150+ go
151+ go
152+
139153-- | 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
140154{-# INLINABLE deleteUpTo #-}
141155deleteUpTo :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
@@ -381,6 +395,24 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
381395 wrapRawElement = wrap
382396
383397instance (Reflex t, MonadAdjust t m, MonadIO m, MonadHold t m, PerformEvent t m, MonadIO (Performable m)) => MonadAdjust t (ImmediateDomBuilderT t m) where
398+ runWithReplace a0 a' = do
399+ initialEnv <- ImmediateDomBuilderT ask
400+ before <- textNodeInternal ("" :: Text)
401+ -- We draw 'after' in this roundabout way to avoid using MonadFix
402+ Just after <- createTextNode (_immediateDomBuilderEnv_document initialEnv) ("" :: Text)
403+ let drawInitialChild = do
404+ result <- a0
405+ append after
406+ return result
407+ (result0, result') <- lift $ runWithReplace (runImmediateDomBuilderT drawInitialChild initialEnv) $ ffor a' $ \child -> do
408+ Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
409+ result <- runImmediateDomBuilderT child $ initialEnv
410+ { _immediateDomBuilderEnv_parent = toNode df
411+ }
412+ deleteBetweenExclusive before after
413+ insertBefore df after
414+ return result
415+ return (result0, result')
384416 sequenceDMapWithAdjust (dm0 :: DMap k (ImmediateDomBuilderT t m)) dm' = do
385417 initialEnv <- ImmediateDomBuilderT ask
386418 let drawChildInitial :: ImmediateDomBuilderT t m a -> m (DOM.DocumentFragment, DOM.Text, a)
src/Reflex/Dom/Builder/InputDisabled.hs+1
@@ -67,6 +67,7 @@ instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (InputDisabl
6767 newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
6868
6969instance MonadAdjust t m => MonadAdjust t (InputDisabledT m) where
70+ runWithReplace a0 a' = InputDisabledT $ runWithReplace (coerce a0) (coerceEvent a')
7071 sequenceDMapWithAdjust dm0 dm' = InputDisabledT $ sequenceDMapWithAdjust (coerce dm0) (coerceEvent dm')
7172
7273instance DomBuilder t m => DomBuilder t (InputDisabledT m) where
src/Reflex/Dom/Builder/Static.hs+5
@@ -138,6 +138,11 @@ instance DomSpace StaticDomSpace where
138138 addEventSpecFlags _ _ _ _ = StaticEventSpec
139139
140140instance (Reflex t, MonadAdjust t m, MonadHold t m) => MonadAdjust t (StaticDomBuilderT t m) where
141+ runWithReplace a0 a' = do
142+ (result0, result') <- lift $ runWithReplace (runStaticDomBuilderT a0) (runStaticDomBuilderT <$> a')
143+ o <- hold (snd result0) $ snd <$> result'
144+ StaticDomBuilderT $ modify $ (:) $ join o
145+ return (fst result0, fst <$> result')
141146 sequenceDMapWithAdjust (dm0 :: DMap k (StaticDomBuilderT t m)) dm' = do
142147 let loweredDm0 = mapKeyValuePairsMonotonic (\(k :=> v) -> WrapArg k :=> fmap swap (runStaticDomBuilderT v)) dm0
143148 loweredDm' = ffor dm' $ \(PatchDMap p) -> PatchDMap $
src/Reflex/Dom/Old.hs+1−16
@@ -21,7 +21,6 @@ module Reflex.Dom.Old
2121 , buildElement
2222 , buildEmptyElement
2323 , buildEmptyElementNS
24− , deleteBetweenExclusive
2524 , elDynHtml'
2625 , elDynHtmlAttr'
2726 , elStopPropagationNS
@@ -60,7 +59,7 @@ import Foreign.JavaScript.TH
6059import qualified GHCJS.DOM.Element as Element
6160import GHCJS.DOM.EventM (EventM)
6261import GHCJS.DOM.NamedNodeMap as NNM
63−import GHCJS.DOM.Node (getFirstChild, getNodeName, getParentNode, getPreviousSibling, removeChild, toNode)
62+import GHCJS.DOM.Node (getFirstChild, getNodeName, removeChild)
6463import GHCJS.DOM.Types (IsElement, IsNode)
6564import qualified GHCJS.DOM.Types as DOM
6665import Reflex.Class
@@ -150,20 +149,6 @@ addDynamicAttributes attrs cfg = do
150149buildElementCommon :: MonadWidget t m => Text -> m a -> ElementConfig er t m -> m (Element er (DomBuilderSpace m) t, a)
151150buildElementCommon elementTag child cfg = element elementTag cfg child
152151
153−-- | s and e must both be children of the same node and s must precede e
154−deleteBetweenExclusive :: (IsNode start, IsNode end) => start -> end -> IO ()
155−deleteBetweenExclusive s e = do
156− 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
157− case mCurrentParent of
158− Nothing -> return () --TODO: Is this the right behavior?
159− Just currentParent -> do
160− let go = do
161− Just x <- getPreviousSibling e -- This can't be Nothing because we should hit 's' first
162− when (toNode s /= toNode x) $ do
163− _ <- removeChild currentParent $ Just x
164− go
165− go
166−
167152onEventName :: IsElement e => EventName en -> e -> EventM e (EventType en) () -> IO (IO ())
168153onEventName = elementOnEventName
169154
src/Reflex/Dom/Widget/Basic.hs+1−9
@@ -91,7 +91,6 @@ import Control.Lens hiding (children, element)
9191import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
9292import Data.Align
9393import Data.Default
94−import qualified Data.Dependent.Map as DMap
9594import Data.Either
9695import Data.Foldable
9796import Data.Functor.Misc
@@ -106,15 +105,8 @@ import Data.These
106105import Data.Traversable
107106import Prelude hiding (mapM, mapM_, sequence, sequence_)
108107
109−--TODO: Implement this specially
110108widgetHoldInternal :: forall t m a b. DomBuilder t m => m a -> Event t (m b) -> m (a, Event t b)
111−widgetHoldInternal child0 child' = do
112− (result0, result') <- sequenceDMapWithAdjust (DMap.singleton LeftTag child0) $ fmap (PatchDMap . DMap.insert LeftTag (ComposeMaybe Nothing) . DMap.singleton RightTag . ComposeMaybe . Just) child'
113− let e :: forall x. x
114− e = error "widgetHoldInternal: missing child (should be impossible)"
115− return ( runIdentity $ DMap.findWithDefault e LeftTag result0
116− , ffor result' $ \(PatchDMap p) -> runIdentity $ fromMaybe e $ getComposeMaybe $ DMap.findWithDefault e RightTag p
117− )
109+widgetHoldInternal = runWithReplace
118110
119111-- | Breaks the given Map into pieces based on the given Set. Each piece will contain only keys that are less than the key of the piece, and greater than or equal to the key of the piece with the next-smaller key. There will be one additional piece containing all keys from the original Map that are larger or equal to the largest key in the Set.
120112-- Either k () is used instead of Maybe k so that the resulting map of pieces is sorted so that the additional piece has the largest key.