@@ -415,6 +415,61 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
415415 placeRawElement = append
416416 wrapRawElement = wrap
417417
418+data FragmentState
419+ = FragmentState_Unmounted
420+ | FragmentState_Mounted (DOM.Text, DOM.Text)
421+
422+data ImmediateDomFragment = ImmediateDomFragment
423+ { _immediateDomFragment_document :: DOM.DocumentFragment
424+ , _immediateDomFragment_state :: IORef FragmentState
425+ }
426+
427+extractFragment :: MonadIO m => ImmediateDomFragment -> m ()
428+extractFragment fragment = do
429+ state <- liftIO $ readIORef $ _immediateDomFragment_state fragment
430+ case state of
431+ FragmentState_Unmounted -> return ()
432+ FragmentState_Mounted (before, after) -> do
433+ extractBetweenExclusive (_immediateDomFragment_document fragment) before after
434+ liftIO $ writeIORef (_immediateDomFragment_state fragment) FragmentState_Unmounted
435+
436+-- | s and e must both be children of the same node and s must precede e; all
437+-- nodes between s and e will be moved into the given DocumentFragment, but s
438+-- and e will not be moved
439+extractBetweenExclusive :: (MonadIO m, IsNode start, IsNode end) => DOM.DocumentFragment -> start -> end -> m ()
440+extractBetweenExclusive df s e = go
441+ where
442+ go = do
443+ Just x <- getNextSibling s -- This can't be Nothing because we should hit 'e' first
444+ when (toNode e /= toNode x) $ do
445+ _ <- appendChild df $ Just x
446+ go
447+
448+instance SupportsImmediateDomBuilder t m => MountableDomBuilder t (ImmediateDomBuilderT t m) where
449+ type DomFragment (ImmediateDomBuilderT t m) = ImmediateDomFragment
450+ buildDomFragment w = do
451+ initialEnv <- ImmediateDomBuilderT ask
452+ Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
453+ result <- lift $ runImmediateDomBuilderT w $ initialEnv
454+ { _immediateDomBuilderEnv_parent = toNode df
455+ }
456+ state <- liftIO $ newIORef FragmentState_Unmounted
457+ return (ImmediateDomFragment df state, result)
458+ mountDomFragment fragment setFragment = do
459+ parent <- askParent
460+ extractFragment fragment
461+ before <- textNodeInternal ("" :: Text)
462+ _ <- appendChild parent $ Just $ _immediateDomFragment_document fragment
463+ after <- textNodeInternal ("" :: Text)
464+ xs <- foldDyn (\new (previous, _) -> (new, Just previous)) (fragment, Nothing) setFragment
465+ performEvent_ $ ffor (updated xs) $ \(childFragment, Just previousFragment) -> do
466+ extractFragment previousFragment
467+ extractFragment childFragment
468+ insertBefore (_immediateDomFragment_document childFragment) after
469+ liftIO $ writeIORef (_immediateDomFragment_state childFragment) $ FragmentState_Mounted (before, after)
470+ liftIO $ writeIORef (_immediateDomFragment_state fragment) $ FragmentState_Mounted (before, after)
471+
472+
418473instance (Reflex t, MonadAdjust t m, MonadIO m, MonadHold t m, PerformEvent t m, MonadIO (Performable m)) => MonadAdjust t (ImmediateDomBuilderT t m) where
419474 runWithReplace a0 a' = do
420475 initialEnv <- ImmediateDomBuilderT ask
@@ -538,6 +593,9 @@ instance PerformEvent t m => PerformEvent t (ImmediateDomBuilderT t m) where
538593 {-# INLINABLE performEvent #-}
539594 performEvent e = lift $ performEvent e
540595
596+instance ExhaustiblePerformEvent t m => ExhaustiblePerformEvent t (ImmediateDomBuilderT t m) where
597+ withPerformEventExhausted a = liftWith $ \run -> withPerformEventExhausted $ run a
598+
541599instance PostBuild t m => PostBuild t (ImmediateDomBuilderT t m) where
542600 {-# INLINABLE getPostBuild #-}
543601 getPostBuild = lift getPostBuild
@@ -1019,58 +1077,3 @@ wrapWindow wv _ = do
10191077 }
10201078
10211079makeLenses ''GhcjsEventSpec
1022−
1023−data FragmentState
1024− = FragmentState_Created
1025− | FragmentState_Mounted (DOM.Text, DOM.Text)
1026−
1027−data DomFragment = DomFragment
1028− { _domFragment_document :: DOM.DocumentFragment
1029− , _domFragment_state :: IORef FragmentState
1030− }
1031−
1032−domFragment :: MonadIO m => ImmediateDomBuilderT t m a -> ImmediateDomBuilderT t m (DomFragment, a)
1033−domFragment w = do
1034− initialEnv <- ImmediateDomBuilderT ask
1035− Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
1036− result <- lift $ runImmediateDomBuilderT w $ initialEnv
1037− { _immediateDomBuilderEnv_parent = toNode df
1038− }
1039− state <- liftIO $ newIORef FragmentState_Created
1040− return (DomFragment df state, result)
1041−
1042−mountDomFragment :: (PerformEvent t m, MonadIO m, MonadIO (Performable m), MonadFix m, MonadHold t m) => DomFragment -> Event t DomFragment -> ImmediateDomBuilderT t m ()
1043−mountDomFragment fragment setFragment = do
1044− parent <- askParent
1045− extractFragment fragment
1046− before <- textNodeInternal ("" :: Text)
1047− _ <- appendChild parent $ Just $ _domFragment_document fragment
1048− after <- textNodeInternal ("" :: Text)
1049− xs <- foldDyn (\new (previous, _) -> (new, Just previous)) (fragment, Nothing) setFragment
1050− performEvent_ $ ffor (updated xs) $ \(childFragment, Just previousFragment) -> do
1051− extractFragment previousFragment
1052− extractFragment childFragment
1053− insertBefore (_domFragment_document childFragment) after
1054− liftIO $ writeIORef (_domFragment_state childFragment) $ FragmentState_Mounted (before, after)
1055− liftIO $ writeIORef (_domFragment_state fragment) $ FragmentState_Mounted (before, after)
1056−
1057−extractFragment :: MonadIO m => DomFragment -> m ()
1058−extractFragment fragment = do
1059− state <- liftIO $ readIORef $ _domFragment_state fragment
1060− case state of
1061− FragmentState_Created -> return ()
1062− FragmentState_Mounted (before, after) -> do
1063− extractBetweenExclusive (_domFragment_document fragment) before after
1064− liftIO $ writeIORef (_domFragment_state fragment) FragmentState_Created
1065−
1066−-- | s and e must both be children of the same node and s must precede e; all
1067−-- nodes between s and e will be moved into the given DocumentFragment, but s
1068−-- and e will not be moved
1069−extractBetweenExclusive :: (MonadIO m, IsNode start, IsNode end) => DOM.DocumentFragment -> start -> end -> m ()
1070−extractBetweenExclusive df s e = go
1071− where
1072− go = do
1073− Just x <- getNextSibling s -- This can't be Nothing because we should hit 'e' first
1074− when (toNode e /= toNode x) $ do
1075− _ <- appendChild df $ Just x
1076− go