9
9
{-# LANGUAGE AllowAmbiguousTypes #-}
10
10
{-# LANGUAGE DataKinds #-}
11
11
{-# OPTIONS_GHC -Wall #-}
12
- module Clickable.Html where
12
+ module Clickable.HTML where
13
13
14
14
import Clickable.Internal
15
15
import Clickable.Types
@@ -19,90 +19,90 @@ import Data.Text (Text)
19
19
import GHC.Generics (Generic )
20
20
import Unsafe.Coerce (unsafeCoerce )
21
21
22
- el :: Text -> HtmlM a -> HtmlM a
23
- el tagName child = HtmlM \ s e -> do
22
+ el :: Text -> HTML a -> HTML a
23
+ el tagName child = HTML \ s e -> do
24
24
e. hte_send $ PushStack $ CreateElement tagName
25
- (r, _) <- child. unHtmlM Nothing e
25
+ (r, _) <- child. unHTML Nothing e
26
26
e. hte_send PopIns
27
27
pure (r, s)
28
28
{-# INLINE el #-}
29
29
30
- elns :: Text -> Text -> HtmlM a -> HtmlM a
31
- elns ns tagName child = HtmlM \ s e -> do
30
+ elns :: Text -> Text -> HTML a -> HTML a
31
+ elns ns tagName child = HTML \ s e -> do
32
32
e. hte_send $ PushStack $ CreateElementNS ns tagName
33
- (r, _) <- child. unHtmlM s e
33
+ (r, _) <- child. unHTML s e
34
34
e. hte_send PopIns
35
35
pure (r, s)
36
36
{-# INLINE elns #-}
37
37
38
- text :: Text -> HtmlM ()
39
- text content = HtmlM \ s e -> do
38
+ text :: Text -> HTML ()
39
+ text content = HTML \ s e -> do
40
40
e. hte_send $ PushStack $ CreateTextNode content
41
41
e. hte_send PopIns
42
42
return (() , s)
43
43
{-# INLINE text #-}
44
44
45
- dynText :: DynVal Text -> HtmlM ()
46
- dynText contentDyn = HtmlM \ s e -> do
45
+ dynText :: Dynamic Text -> HTML ()
46
+ dynText contentDyn = HTML \ s e -> do
47
47
c <- readVal contentDyn
48
- refId <- newRefId. unClickM e
48
+ refId <- newRefId. unJSM e
49
49
e. hte_send $ PushStack $ CreateTextNode c
50
50
e. hte_send $ AssignRef refId (PeekStack 0 )
51
51
e. hte_send PopIns
52
- let k nval = ClickM \ e' ->
52
+ let k nval = JSM \ e' ->
53
53
e'. hte_send $ UpdateTextNode (Ref refId) nval
54
- (subscribe contentDyn k). unClickM e
54
+ (subscribe contentDyn k). unJSM e
55
55
pure (() , s)
56
56
{-# INLINEABLE dynText #-}
57
57
58
- property :: ToValue val => Text -> val -> HtmlM ()
59
- property k v = HtmlM \ s e -> do
58
+ property :: ToValue val => Text -> val -> HTML ()
59
+ property k v = HTML \ s e -> do
60
60
e. hte_send $ ElementProp (PeekStack 0 ) k $ toValue v
61
61
pure (() , s)
62
62
{-# INLINE property #-}
63
63
64
- dynProp :: ToValue val => Text -> DynVal val -> HtmlM ()
65
- dynProp propName dynVal = HtmlM \ s e -> do
66
- (refId, s') <- saveStackTip. unHtmlM s e
64
+ dynProp :: ToValue val => Text -> Dynamic val -> HTML ()
65
+ dynProp propName dynVal = HTML \ s e -> do
66
+ (refId, s') <- saveStackTip. unHTML s e
67
67
initVal <- readVal dynVal
68
68
e. hte_send $ ElementProp (PeekStack 0 ) propName $ toValue initVal
69
- let k nval = ClickM \ e' ->
69
+ let k nval = JSM \ e' ->
70
70
e'. hte_send $ ElementProp (Ref refId) propName $ toValue nval
71
- unClickM (subscribe dynVal k) e
71
+ unJSM (subscribe dynVal k) e
72
72
pure (() , s')
73
73
{-# INLINE dynProp #-}
74
74
75
- attribute :: Text -> Text -> HtmlM ()
76
- attribute k v = HtmlM \ s e -> do
75
+ attribute :: Text -> Text -> HTML ()
76
+ attribute k v = HTML \ s e -> do
77
77
e. hte_send $ ElementAttr (PeekStack 0 ) k v
78
78
pure (() , s)
79
79
{-# INLINE attribute #-}
80
80
81
- dynAttr :: Text -> DynVal Text -> HtmlM ()
82
- dynAttr propName dynVal = HtmlM \ s e -> do
83
- (refId, s') <- saveStackTip. unHtmlM s e
81
+ dynAttr :: Text -> Dynamic Text -> HTML ()
82
+ dynAttr propName dynVal = HTML \ s e -> do
83
+ (refId, s') <- saveStackTip. unHTML s e
84
84
initVal <- readVal dynVal
85
85
e. hte_send $ ElementAttr (PeekStack 0 ) propName initVal
86
- let k nval = ClickM \ e' ->
86
+ let k nval = JSM \ e' ->
87
87
e'. hte_send $ ElementAttr (Ref refId) propName nval
88
- unClickM (subscribe dynVal k) e
88
+ unJSM (subscribe dynVal k) e
89
89
pure (() , s')
90
90
{-# INLINE dynAttr #-}
91
91
92
- toggleClass :: Text -> DynVal Bool -> HtmlM ()
93
- toggleClass className dynEnable = HtmlM \ s e -> do
94
- (refId, s') <- saveStackTip. unHtmlM s e
92
+ toggleClass :: Text -> Dynamic Bool -> HTML ()
93
+ toggleClass className dynEnable = HTML \ s e -> do
94
+ (refId, s') <- saveStackTip. unHTML s e
95
95
v <- readVal dynEnable
96
- let k enable = ClickM \ e' -> e'. hte_send
96
+ let k enable = JSM \ e' -> e'. hte_send
97
97
if enable
98
98
then ClassListAdd (Ref refId) className
99
99
else ClassListRemove (Ref refId) className
100
- unClickM (k v) e
101
- unClickM (subscribe dynEnable k) e
100
+ unJSM (k v) e
101
+ unJSM (subscribe dynEnable k) e
102
102
pure (() , s')
103
103
{-# INLINE toggleClass #-}
104
104
105
- addEventListener :: FromValue a => (Event a -> Expr ) -> (a -> ClickM () ) -> ClickM ()
105
+ addEventListener :: FromValue a => (Event a -> Expr ) -> (a -> JSM () ) -> JSM ()
106
106
addEventListener connectScript k = do
107
107
e <- reactive \ scope s ->
108
108
let k' = local (\ e -> e {hte_scope = scope}) . k
@@ -116,13 +116,13 @@ addEventListener connectScript k = do
116
116
117
117
class IsEventName eventName where
118
118
type EventListenerCb eventName :: Type
119
- connectEventName :: EventListenerCb eventName -> ClickM ()
119
+ connectEventName :: EventListenerCb eventName -> JSM ()
120
120
121
- on :: forall eventName . IsEventName eventName => EventListenerCb eventName -> HtmlM ()
122
- on k = liftC $ connectEventName @ eventName k
121
+ on :: forall eventName . IsEventName eventName => EventListenerCb eventName -> HTML ()
122
+ on k = liftJSM $ connectEventName @ eventName k
123
123
124
124
instance IsEventName " click" where
125
- type EventListenerCb " click" = ClickM ()
125
+ type EventListenerCb " click" = JSM ()
126
126
connectEventName k = addEventListener
127
127
(genericEvent defaultEventListenerOptions " click" (PeekStack 0 )) (const k)
128
128
@@ -157,21 +157,21 @@ unsafeConnectEvent :: Expr -> UnsafeJavaScript -> Event a -> Expr
157
157
unsafeConnectEvent target ujs (Event eid) =
158
158
Eval ujs `Apply ` [target, Lam (TriggerEvent eid (Arg 0 ))]
159
159
160
- attachHtml :: Expr -> HtmlM a -> ClickM a
161
- attachHtml rootEl contents = ClickM \ e -> do
160
+ attachHTML :: Expr -> HTML a -> JSM a
161
+ attachHTML rootEl contents = JSM \ e -> do
162
162
e. hte_send $ PushStack rootEl
163
- (r, _) <- contents. unHtmlM Nothing e
163
+ (r, _) <- contents. unHTML Nothing e
164
164
e. hte_send PopStack
165
165
pure r
166
166
167
- attachToBody :: HtmlM a -> ClickM a
168
- attachToBody = attachHtml $ Id " document" `Dot ` " body"
167
+ attachToBody :: HTML a -> JSM a
168
+ attachToBody = attachHTML $ Id " document" `Dot ` " body"
169
169
170
- saveStackTip :: HtmlM RefId
171
- saveStackTip = HtmlM \ s e ->
170
+ saveStackTip :: HTML RefId
171
+ saveStackTip = HTML \ s e ->
172
172
case s of
173
173
Nothing -> do
174
- refId <- newRefId. unClickM e
174
+ refId <- newRefId. unJSM e
175
175
e. hte_send $ AssignRef refId $ PeekStack 0
176
176
return (refId, Just refId)
177
177
Just saved ->
@@ -180,3 +180,42 @@ saveStackTip = HtmlM \s e ->
180
180
blank :: Applicative m => m ()
181
181
blank = pure ()
182
182
{-# INLINE blank #-}
183
+
184
+ data Location = Location {
185
+ -- | A string containing the protocol scheme of the URL, including
186
+ -- the final ':'
187
+ protocol :: Text ,
188
+ -- | A string containing the domain of the URL.
189
+ hostname :: Text ,
190
+ -- | A string containing the port number of the URL.
191
+ port :: Text ,
192
+ -- | A string containing an initial '/' followed by the path of the
193
+ -- URL, not including the query string or fragment.
194
+ pathname :: Text ,
195
+ -- | String containing a '?' followed by the parameters or
196
+ -- "querystring" of the URL
197
+ search :: Text ,
198
+ -- | String containing a '#' followed by the fragment identifier
199
+ -- of the URL.
200
+ hash :: Text
201
+ } deriving stock (Show , Eq , Generic )
202
+ deriving anyclass (FromValue , ToValue )
203
+
204
+ -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event
205
+ popstateEvent :: Event Location -> Expr
206
+ popstateEvent (Event eventId) =
207
+ Eval
208
+ " (function(target, trigger){\n \
209
+ \ function listener(){\n \
210
+ \ trigger({\n \
211
+ \ protocol: location.protocol,\n \
212
+ \ hostname: location.hostname,\n \
213
+ \ port: location.port,\n \
214
+ \ pathname: location.pathname,\n \
215
+ \ search: location.search,\n \
216
+ \ hash: location.hash\n \
217
+ \ });\n \
218
+ \ }\n \
219
+ \ target.addEventListener('popstate', listener);\n \
220
+ \ return () => target.removeEventListener('popstate', listener);\n \
221
+ \})" `Apply ` [Id " window" , Lam (TriggerEvent eventId (Arg 0 ))]
0 commit comments