A ClojureScript library designed to make it easy to get your Single Page Application to behave more like a ”regular” site would do when it comes to navigating between, and within, pages.
Clerk takes care of the scroll positioning when:
Clerk does not deal with anything else beside of the above. Use it together wih your routing and HTML5 history libararies of choice.
Today's web browsers handles all this automatic scroll positioniing perfectly for regular sites. But the S in SPA really means that everything happens on the same page, even if it looks to the user as if navigatin between pages happens. A new page is just the result of rendering new content. So without managing the scroll positioning we have this Ux problem:
In addition to this:
Let Clerk take care of all this for you!
Add the dependency:
[pez/clerk "0.1.0"]
The examples in this README assumes Clerk is required like so:
(:require
...
[clerk.core :as clerk]
...
Initialize as early as possible when your app is starting:
(clerk/initialize!)
After any routing/navigation dispatch of your app you need to tell Clerk about the new path
(clerk/navigate-page! path)
Then just one more thing. To avoid flicker, Clerk deferrs scroll adjustment until after the page is rendered. You need to tell Clerk when rendering is done:
(clerk/after-render!)
Depending on your project the after render notification will need to be injected in different ways. Here are exemples for two common ClojureScript React frameworks, Rum and Reagent:
Clerk has a utility Rum mixin for after-render. Use like so:
(defc page < rum/reactive
clerk/rum-after-render
...
For Reagent, you can use the reagent/after-render
function, which calls any function you provide to it when rendering is done:
(reagent/after-render clerk/after-render!)
The Leiningen Reagent template's init!
function will look lie so with all clerky stuff added:
(defn init! []
(clerk/initialize!)
(accountant/configure-navigation!
{:nav-handler
(fn [path]
(reagent/after-render clerk/after-render!)
(secretary/dispatch! path)
(clerk/navigate-page! path))
:path-exists?
(fn [path]
(secretary/locate-route path))})
(accountant/dispatch-current!)
(mount-root))
(For Rum it will look very similar, except that you need to use a mixin for your page component's :after-render
callback instead of using the reagent/after-render
.)
IMPORTANT: If you are using some kind of analytics (like Google Analytics) for stats on site usage for your SPA, take care with any history change events resulting in ”virtual” page hits. Clerk uses the browser's history state to store the current scroll position for the page. Specifically, the default History Change Trigger of Google Tag Manager can't be used as is. You risk spamming your stats with ”page views” that really are just the user scrolling.
In Scotland, the term scrow was used from about the 13th to the 17th centuries for scroll, writing, or documents in list or schedule form. There existed an office of Clerk of the Scrow (Rotulorum Clericus) meaning the Clerk of the Rolls or Clerk of the Register. (From [WikiPedia].(https://en.wikipedia.org/wiki/Scroll#Scotland))
Also, it is quite beautiful to imagine that with some projects maybe Secretary, Accountant and Clerk will work together to get the SPA to behave according to the expectations of its users.
Questions, suggestions, PRs. Just throw it at me. File issues at will. You can also most often find me at the Clojurians Slack. Have praise? Tweet it! Tag @pappapez.
Copyright © 2018 Peter Strömberg
Distributed under the Eclipse Public License, either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close