Refactor ignore-anchor-click check to predicate function

This commit is contained in:
Juho Teperi 2019-04-26 15:10:17 +03:00
parent 5ffb9fc59f
commit 51c5aad492
2 changed files with 44 additions and 38 deletions

View file

@ -31,8 +31,10 @@ event handling:
(rfe/start! (rfe/start!
router router
{:use-fragment false {:use-fragment false
:ignore-anchor-click (fn [e el] :ignore-anchor-click? (fn [router e el uri]
(not= "false" (gobj/get (.-dataset el) "reititHandleClick")))}) ;; Add additional check on top of the default checks
(and (rfh/ignore-anchor-click? router e el uri)
(not= "false" (gobj/get (.-dataset el) "reititHandleClick"))))})
;; Use data-reitit-handle-click to disable Reitit anchor handling ;; Use data-reitit-handle-click to disable Reitit anchor handling
[:a [:a

View file

@ -67,6 +67,29 @@
(first (.composedPath original-event)) (first (.composedPath original-event))
(.-target event)))) (.-target event))))
(defn ignore-anchor-click?
"Precicate to check if the anchor click event default action
should be ignored. This logic will ignore the event
if anchor href matches the route tree, and in this case
the page location is updated using History API."
[router e el uri]
(let [current-domain (if (exists? js/location)
(.getDomain (.parse Uri js/location)))]
(and (or (and (not (.hasScheme uri)) (not (.hasDomain uri)))
(= current-domain (.getDomain uri)))
(not (.-altKey e))
(not (.-ctrlKey e))
(not (.-metaKey e))
(not (.-shiftKey e))
(or (not (.hasAttribute el "target"))
(contains? #{"" "_self"} (.getAttribute el "target")))
;; Left button
(= 0 (.-button e))
;; isContentEditable property is inherited from parents,
;; so if the anchor is inside contenteditable div, the property will be true.
(not (.-isContentEditable el))
(reitit/match-by-path router (.getPath uri)))))
(defrecord Html5History [on-navigate router listen-key click-listen-key] (defrecord Html5History [on-navigate router listen-key click-listen-key]
History History
(-init [this] (-init [this]
@ -74,42 +97,22 @@
(fn [e] (fn [e]
(-on-navigate this (-get-path this))) (-on-navigate this (-get-path this)))
current-domain ignore-anchor-click-predicate (or (:ignore-anchor-click? this)
(if (exists? js/location) ignore-anchor-click?)
(.getDomain (.parse Uri js/location)))
ignore-anchor-click-fn (or (:ignore-anchor-click this)
(constantly true))
;; Prevent document load when clicking a elements, if the href points to URL that is part ;; Prevent document load when clicking a elements, if the href points to URL that is part
;; of the routing tree." ;; of the routing tree."
ignore-anchor-click ignore-anchor-click (fn [e]
(fn ignore-anchor-click ;; Returns the next matching anchestor of event target
[e] (when-let [el (closest-by-tag (event-target e) "a")]
;; Returns the next matching anchestor of event target (let [uri (.parse Uri (.-href el))]
(when-let [el (closest-by-tag (event-target e) "a")] (when (ignore-anchor-click-predicate router e el uri)
(let [uri (.parse Uri (.-href el))] (.preventDefault e)
(when (and (or (and (not (.hasScheme uri)) (not (.hasDomain uri))) (let [path (str (.getPath uri)
(= current-domain (.getDomain uri))) (if (seq (.getQuery uri))
(not (.-altKey e)) (str "?" (.getQuery uri))))]
(not (.-ctrlKey e)) (.pushState js/window.history nil "" path)
(not (.-metaKey e)) (-on-navigate this path))))))]
(not (.-shiftKey e))
(or (not (.hasAttribute el "target"))
(contains? #{"" "_self"} (.getAttribute el "target")))
;; Left button
(= 0 (.-button e))
;; isContentEditable property is inherited from parents,
;; so if the anchor is inside contenteditable div, the property will be true.
(not (.-isContentEditable el))
(ignore-anchor-click-fn e el)
(reitit/match-by-path router (.getPath uri)))
(.preventDefault e)
(let [path (str (.getPath uri)
(if (seq (.getQuery uri))
(str "?" (.getQuery uri))))]
(.pushState js/window.history nil "" path)
(-on-navigate this path))))))]
(-on-navigate this (-get-path this)) (-on-navigate this (-get-path this))
(assoc this (assoc this
:listen-key (gevents/listen js/window goog.events.EventType.POPSTATE handler false) :listen-key (gevents/listen js/window goog.events.EventType.POPSTATE handler false)
@ -141,9 +144,10 @@
- :use-fragment (default true) If true, onhashchange and location hash are used to store current route. - :use-fragment (default true) If true, onhashchange and location hash are used to store current route.
Options (Html5History): Options (Html5History):
- :ignore-anchor-click Function (event, anchor element) to check if Reitit - :ignore-anchor-click? Function (router, event, anchor element, uri) which will be called to
should handle click events on the anchor element. By default check if the anchor click event should be ignored.
hrefs matching the route tree are handled by Reitit." To extend built-in check, you can call `reitit.frontend.history/ignore-anchor-click?`
function, which will ignore clicks if the href matches route tree."
([router on-navigate] ([router on-navigate]
(start! router on-navigate nil)) (start! router on-navigate nil))
([router ([router