hoplon / hoplon

Simple and powerful tool for building web apps out of highly composable elements in ClojureScript.
https://hoplon.io/
Eclipse Public License 1.0
1.02k stars 65 forks source link

a browser history cell #172

Closed thedavidmeister closed 7 years ago

thedavidmeister commented 7 years ago

We have route cells but it simply responds to the hash change event.

I found that this wasn't really working in phantomjs and google closure has a history class with lots of x-browser handling around navigation.

I made a history cell that is based on google closure and it works much better for me:

(defn history-cell
 []
 (let [c (j/cell nil)
       history (History.)]
  (j/with-let [_ (j/cell= c #(.setToken history %))]
   (goog.events/listen history goog.History/EventType.NAVIGATE
    (fn [e]
     (reset! c (.-token e))))
   (.setEnabled history true))))

It's almost a drop in replacement for route-cell except that it expects you to reset the cell in order to navigate, rather than mess around with the window hash directly.

e.g.

route cell:

(defc foo (route-cell))
(prn @foo) ; ""
(-> js/window .-location .-hash (set! "foo"))
(prn @foo) ; "foo"

vs. history-cell:

(defc foo (history-cell))
(prn @foo) ; ""
(reset! foo "foo")
(prn @foo) ; "foo"
thedavidmeister commented 7 years ago

here's the whole thing, with passing tests:

(ns route.history
 (:require goog.History
           goog.events
           [javelin.core :as j]
           [cljs.test :refer-macros [deftest is]])
 (:import [goog History]))

(defn history-cell
 []
 (let [c (j/cell nil)
       history (History.)]
  (j/with-let [_ (j/cell= c #(.setToken history %))]
   (goog.events/listen history goog.History/EventType.NAVIGATE
    (fn [e]
     (reset! c (.-token e))))
   (.setEnabled history true))))

(deftest ??history-cell
 (let [c (history-cell)
       current-hash #(-> js/window .-location .-hash)]
  ; Is c correctly initialized to some hash?
  (is (not (nil? @c)))
  (is (string? @c))

  ; Can we set c by modifying the window hash directly?
  (-> js/window .-location .-hash (set! "foo"))
  (= "foo" @c (current-hash))

  ; Can we set c and the window hash by resetting c?
  (reset! c "bar")
  (= "bar" @c (current-hash))))
burn2delete commented 7 years ago

Nice work!

burn2delete commented 7 years ago

@thedavidmeister can we get a PR for this in hoplon/brew?

thedavidmeister commented 7 years ago

@flyboarder soz, i didn't put this against hoplon/brew but i have put it somewhere slightly more useful than a codeblock here (running tests, etc.) https://github.com/thedavidmeister/wheel/blob/master/src/wheel/route/core.cljs#L19

burn2delete commented 7 years ago

I added this to hoplon/brew as well.