Skip to content

Instantly share code, notes, and snippets.

@dustingetz
Last active September 10, 2022 19:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dustingetz/b2ccbdf8b4bdaf7c982998a960c323a4 to your computer and use it in GitHub Desktop.
Save dustingetz/b2ccbdf8b4bdaf7c982998a960c323a4 to your computer and use it in GitHub Desktop.
photon infinite scroll over node-modules

Photon demo: infinite scroll over node-modules

  • 100% of server data sync is managed by Photon
  • Rows have arbitrary server local data access, here querying file metadata #clojure
20220906.infinite.scroll.node.modules.mp4

Below is the approximate code (I've removed all the table/file stuff to just see the essential scroll logic)

#?(:cljs (defn sample-scroll-state! [scrollable]
[(.. scrollable -scrollTop)
(.. scrollable -scrollHeight)
(.. scrollable -clientHeight)]))
#?(:cljs (defn scroll-state> [scrollable]
(m/observe
(fn [!]
(let [sample (fn [] (! (sample-scroll-state! scrollable)))]
(.addEventListener scrollable "scroll" sample #js {"passive" true})
#(.removeEventListener scrollable "scroll" sample))))))
#?(:cljs (defn scroll-state< [scrollable]
(->> (scroll-state> scrollable)
(m/reductions {} [0 0 0])
(m/latest identity))))
; counted collection, fixed/known row height, absolute "jump scroll"
(p/client
(dom/div {:style {:overflowX "hidden" :overflowY "auto"}}
(let [[scrollTop] (new (scroll-state< dom/node))
max-height (* row-count row-height)
clamped-scroll-top (js/Math.min scrollTop max-height)
start (/ clamped-scroll-top row-height)]
(dom/div {:style {:height (str (* row-height row-count) "px") ; allow absolute jumps when height and count are known
:padding-top (str clamped-scroll-top "px") ; seen elements are replaced with padding
:padding-bottom (str (- max-height clamped-scroll-top) "px")}}
(p/server
(p/for [x (->> xs (drop start) (take page-size))]
(p/client (dom/div x))))))))
; infinite seq, variable row height, uses natural layout at cost of leaving seen elements mounted
(p/client
(dom/div {:style {:overflowX "hidden" :overflowY "auto"}}
(let [!pages (atom 1) pages (p/watch !pages)
[scrollTop scrollHeight clientHeight] (new (scroll-state< dom/node))]
(when (>= scrollTop (- scrollHeight clientHeight
clientHeight)) ; scrollThresholdPx = clientHeight
(swap! !pages inc))
(dom/div ; content is unstyled, uses natural layout
(p/server
(p/for [x (->> xs (take (* pages page-size)))] ; leave dom
(p/client (dom/div x))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment