1{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE ExplicitForAll #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE Rank2Types #-}
7{-# LANGUAGE ScopedTypeVariables #-}
8{-# LANGUAGE TemplateHaskell #-}
9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE UndecidableInstances #-}
35 , namedNodeMapGetNames
45import Control.Arrow (first)
46import Control.Lens (makeLenses, (%~), (&), (.~), (^.))
48import Control.Monad.Fix
49import Control.Monad.IO.Class
50import Control.Monad.Reader
51import Control.Monad.Ref
53import Data.Dependent.Map as DMap
54import Data.Functor.Misc
56import qualified Data.Map as Map
59import qualified Data.Set as Set
61import Foreign.JavaScript.TH
62import qualified GHCJS.DOM.Element as Element
63import GHCJS.DOM.EventM (EventM)
64import GHCJS.DOM.NamedNodeMap as NNM
65import GHCJS.DOM.Node (getFirstChild, getNodeName, removeChild)
66import GHCJS.DOM.Types (IsElement, IsNode)
67import qualified GHCJS.DOM.Types as DOM
69import Reflex.Dom.Builder.Class
70import Reflex.Dom.Builder.Immediate
71import Reflex.Dom.Internal.Foreign
72import Reflex.Dom.Widget.Basic
73import Reflex.Host.Class
74import Reflex.PerformEvent.Class
75import Reflex.PostBuild.Class
76import Reflex.TriggerEvent.Class
78data ElConfig attrs = ElConfig
79 { _elConfig_namespace :: Maybe Text
80 , _elConfig_attributes :: attrs
83instance attrs ~ Map Text Text => Default (ElConfig attrs) where
85 { _elConfig_namespace = Nothing
86 , _elConfig_attributes = mempty
91--TODO: HasDocument is still not accounted for
92type MonadWidgetConstraints t m =
94 , DomBuilderSpace m ~ GhcjsDomSpace
97 , MonadSample t (Performable m)
98 , MonadReflexCreateTrigger t m
102 , MonadIO (Performable m)
105 , HasWebView (Performable m)
108 , MonadRef (Performable m)
109 , Ref (Performable m) ~ Ref IO
112class MonadWidgetConstraints t m => MonadWidget t m
113instance MonadWidgetConstraints t m => MonadWidget t m
115type WidgetHost m = Performable m
117type El = Element EventResult GhcjsDomSpace
119addVoidAction :: MonadWidget t m => Event t (WidgetHost m ()) -> m ()
120addVoidAction = performEvent_
122type AttributeMap = Map Text Text
124buildElement :: (MonadWidget t m, Attributes m attrs t) => Text -> attrs -> m a -> m (RawElement (DomBuilderSpace m), a)
125buildElement = buildElementNS Nothing
127buildEmptyElement :: (MonadWidget t m, Attributes m attrs t) => Text -> attrs -> m (RawElement (DomBuilderSpace m))
128buildEmptyElement elementTag attrs = fst <$> buildElementNS Nothing elementTag attrs blank
130buildEmptyElementNS :: (MonadWidget t m, Attributes m attrs t) => Maybe Text -> Text -> attrs -> m (RawElement (DomBuilderSpace m))
131buildEmptyElementNS ns elementTag attrs = fst <$> buildElementNS ns elementTag attrs blank
133buildElementNS :: (MonadWidget t m, Attributes m attrs t) => Maybe Text -> Text -> attrs -> m a -> m (RawElement (DomBuilderSpace m), a)
134buildElementNS ns elementTag attrs child = first _element_raw <$> buildElementInternal ns elementTag attrs child
136class Attributes m attrs t where
137 buildElementInternal :: MonadWidget t m => Maybe Text -> Text -> attrs -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
139instance Attributes m (Map Text Text) t where
140 buildElementInternal ns elementTag attrs child = do
141 let cfg = def & elementConfig_namespace .~ ns
142 buildElementCommon elementTag child =<< addStaticAttributes attrs cfg
144addStaticAttributes :: Applicative m => Map Text Text -> ElementConfig er t m -> m (ElementConfig er t m)
145addStaticAttributes attrs cfg = do
146 let initialAttrs = Map.fromList $ first (AttributeName Nothing) <$> Map.toList attrs
147 pure $ cfg & elementConfig_initialAttributes .~ initialAttrs
149instance PostBuild t m => Attributes m (Dynamic t (Map Text Text)) t where
150 buildElementInternal ns elementTag attrs child = do
151 let cfg = def & elementConfig_namespace .~ ns
152 buildElementCommon elementTag child =<< addDynamicAttributes attrs cfg
154addDynamicAttributes :: PostBuild t m => Dynamic t (Map Text Text) -> ElementConfig er t m -> m (ElementConfig er t m)
155addDynamicAttributes attrs cfg = do
156 modifyAttrs <- dynamicAttributesToModifyAttributes attrs
157 return $ cfg & elementConfig_modifyAttributes .~ fmap mapKeysToAttributeName modifyAttrs
159buildElementCommon :: MonadWidget t m => Text -> m a -> ElementConfig er t m -> m (Element er (DomBuilderSpace m) t, a)
160buildElementCommon elementTag child cfg = element elementTag cfg child
162onEventName :: IsElement e => EventName en -> e -> EventM e (EventType en) () -> IO (IO ())
163onEventName = elementOnEventName
165schedulePostBuild :: (PostBuild t m, PerformEvent t m) => WidgetHost m () -> m ()
166schedulePostBuild w = do
167 postBuild <- getPostBuild
168 performEvent_ $ w <$ postBuild
170text' :: MonadWidget t m => Text -> m DOM.Text
171text' s = _textNode_raw <$> textNode (def & textNodeConfig_initialContents .~ s)
173instance HasAttributes (ElConfig attrs) where
174 type Attrs (ElConfig attrs) = attrs
175 attributes = elConfig_attributes
177instance HasNamespace (ElConfig attrs) where
178 namespace = elConfig_namespace
180elWith :: (MonadWidget t m, Attributes m attrs t) => Text -> ElConfig attrs -> m a -> m a
181elWith elementTag cfg child = snd <$> elWith' elementTag cfg child
183elWith' :: (MonadWidget t m, Attributes m attrs t) => Text -> ElConfig attrs -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
184elWith' elementTag cfg = buildElementInternal (cfg ^. namespace) elementTag $ cfg ^. attributes
186emptyElWith :: (MonadWidget t m, Attributes m attrs t) => Text -> ElConfig attrs -> m ()
187emptyElWith elementTag cfg = void $ emptyElWith' elementTag cfg
189emptyElWith' :: (MonadWidget t m, Attributes m attrs t) => Text -> ElConfig attrs -> m (Element EventResult (DomBuilderSpace m) t)
190emptyElWith' elementTag cfg = fmap fst $ elWith' elementTag cfg $ return ()
192{-# DEPRECATED _el_clicked "Use 'domEvent Click' instead" #-}
193_el_clicked :: Reflex t => Element EventResult d t -> Event t ()
194_el_clicked = domEvent Click
196{-# DEPRECATED _el_element "Use '_element_raw' instead" #-}
197_el_element :: El t -> RawElement GhcjsDomSpace
198_el_element = _element_raw
200{-# DEPRECATED _el_events "Use '_element_events' instead; or, if possible, use 'domEvent' instead to retrieve a particular event" #-}
201_el_events :: Element er d t -> EventSelector t (WrapArg er EventName)
202_el_events = _element_events
204{-# DEPRECATED _el_keypress "Use 'domEvent Keypress' instead" #-}
205_el_keypress :: Reflex t => El t -> Event t Int
206_el_keypress = domEvent Keypress
208{-# DEPRECATED _el_scrolled "Use 'domEvent Scroll' instead" #-}
209_el_scrolled :: Reflex t => El t -> Event t Int
210_el_scrolled = domEvent Scroll
212wrapElement :: forall t m. MonadWidget t m => (forall en. DOM.Element -> EventName en -> EventM DOM.Element (EventType en) (Maybe (EventResult en))) -> DOM.Element -> m (El t)
214 let h :: (EventName en, GhcjsDomEvent en) -> IO (Maybe (EventResult en))
215 h (en, GhcjsDomEvent evt) = runReaderT (eh e en) evt
216 wrapRawElement e $ (def :: RawElementConfig EventResult t m)
217 { _rawElementConfig_eventSpec = def
218 { _ghcjsEventSpec_handler = h
222unsafePlaceElement :: MonadWidget t m => DOM.Element -> m (Element EventResult (DomBuilderSpace m) t)
223unsafePlaceElement e = do
227namedNodeMapGetNames :: DOM.NamedNodeMap -> IO (Set Text)
228namedNodeMapGetNames self = do
229 l <- NNM.getLength self
230 let locations = if l == 0 then [] else [0..l-1] -- Can't use 0..l-1 if l is 0 because l is unsigned and will wrap around
231 fmap (Set.fromList . catMaybes) $ forM locations $ \i -> do
232 Just n <- NNM.item self i
235nodeClear :: IsNode self => self -> IO ()
237 mfc <- getFirstChild n
241 _ <- removeChild n $ Just fc
244getQuitWidget :: MonadWidget t m => m (WidgetHost m ())
245getQuitWidget = return $ do
246 WebViewSingleton wv <- askWebView
247 liftIO $ quitWebView wv
249elStopPropagationNS :: forall t m en a. (MonadWidget t m) => Maybe Text -> Text -> EventName en -> m a -> m a
250elStopPropagationNS ns elementTag en child = do
251 let f = GhcjsEventFilter $ \_ -> do
252 return (stopPropagation, return Nothing)
253 cfg = (def :: ElementConfig EventResult t m)
255 & elementConfig_eventSpec . ghcjsEventSpec_filters %~ DMap.insert en f
256 snd <$> element elementTag cfg child
258elDynHtmlAttr' :: MonadWidget t m => Text -> Map Text Text -> Dynamic t Text -> m (Element EventResult GhcjsDomSpace t)
259elDynHtmlAttr' elementTag attrs html = do
260 let cfg = def & initialAttributes .~ Map.mapKeys (AttributeName Nothing) attrs
261 (e, _) <- element elementTag cfg $ return ()
262 postBuild <- getPostBuild
263 performEvent_ $ Element.setInnerHTML (_element_raw e) . Just <$> leftmost [updated html, tag (current html) postBuild]
266elDynHtml' :: MonadWidget t m => Text -> Dynamic t Text -> m (Element EventResult GhcjsDomSpace t)
267elDynHtml' elementTag = elDynHtmlAttr' elementTag mempty
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list