Have DOM more or less working with element transitions, cursors implemented, working on items-view.
This commit is contained in:
parent
de3186e8c0
commit
0b1bcc766a
6 changed files with 348 additions and 84 deletions
|
@ -95,3 +95,10 @@ return false or throw an exception."
|
||||||
(atom-view ratom view-fn identity))
|
(atom-view ratom view-fn identity))
|
||||||
([ratom view-fn update-fn]
|
([ratom view-fn update-fn]
|
||||||
(ReactiveAtomView. ratom view-fn update-fn)))
|
(ReactiveAtomView. ratom view-fn update-fn)))
|
||||||
|
|
||||||
|
(def rx* reactive*)
|
||||||
|
|
||||||
|
(defmacro rx [& body]
|
||||||
|
`(freactive.core/rx*
|
||||||
|
(fn []
|
||||||
|
~@body)))
|
||||||
|
|
|
@ -18,17 +18,25 @@
|
||||||
(defn remove-invalidation-watch [this key]
|
(defn remove-invalidation-watch [this key]
|
||||||
(-remove-invalidation-watch this key))
|
(-remove-invalidation-watch this key))
|
||||||
|
|
||||||
|
(defn- force-update-state [a old-value new-value]
|
||||||
|
(set! (.-state a) new-value)
|
||||||
|
(when-not (nil? (.-watches a))
|
||||||
|
(-notify-watches a old-value new-value))
|
||||||
|
(when-not (nil? (.-invalidation-watches a))
|
||||||
|
(-notify-invalidation-watches a))
|
||||||
|
new-value)
|
||||||
|
|
||||||
(deftype ReactiveAtom [state meta validator watches invalidation-watches]
|
(deftype ReactiveAtom [state meta validator watches invalidation-watches]
|
||||||
Object
|
Object
|
||||||
(equiv [this other]
|
(equiv [this other]
|
||||||
(-equiv this other))
|
(-equiv this other))
|
||||||
|
|
||||||
IAtom
|
cljs.core/IAtom
|
||||||
|
|
||||||
IEquiv
|
cljs.core/IEquiv
|
||||||
(-equiv [o other] (identical? o other))
|
(-equiv [o other] (identical? o other))
|
||||||
|
|
||||||
IDeref
|
cljs.core/IDeref
|
||||||
(-deref [this]
|
(-deref [this]
|
||||||
(register-dep this)
|
(register-dep this)
|
||||||
state)
|
state)
|
||||||
|
@ -71,12 +79,8 @@
|
||||||
(when-not (nil? validate)
|
(when-not (nil? validate)
|
||||||
(assert (validate new-value) "Validator rejected reference state"))
|
(assert (validate new-value) "Validator rejected reference state"))
|
||||||
(let [old-value (.-state a)]
|
(let [old-value (.-state a)]
|
||||||
(set! (.-state a) new-value)
|
(when (not= old-value new-value)
|
||||||
(when-not (nil? (.-watches a))
|
(force-update-state a old-value new-value)))))
|
||||||
(-notify-watches a old-value new-value))
|
|
||||||
(when-not (nil? (.-invalidation-watches a))
|
|
||||||
(-notify-invalidation-watches a))
|
|
||||||
new-value)))
|
|
||||||
|
|
||||||
ISwap
|
ISwap
|
||||||
(-swap! [a f]
|
(-swap! [a f]
|
||||||
|
@ -179,3 +183,81 @@
|
||||||
(let [reactive (ReactiveComputation. nil true f nil nil nil nil nil)]
|
(let [reactive (ReactiveComputation. nil true f nil nil nil nil nil)]
|
||||||
(set! (.-sully reactive) (make-sully-fn reactive))
|
(set! (.-sully reactive) (make-sully-fn reactive))
|
||||||
reactive))
|
reactive))
|
||||||
|
|
||||||
|
(defn- do-update-state [cursor new-value]
|
||||||
|
(let [old-value (.-state cursor)]
|
||||||
|
(when (not= old-value new-value)
|
||||||
|
(force-update-state cursor old-value new-value))))
|
||||||
|
|
||||||
|
(deftype Cursor [ref path state meta watches invalidation-watches]
|
||||||
|
Object
|
||||||
|
(equiv [this other]
|
||||||
|
(-equiv this other))
|
||||||
|
|
||||||
|
cljs.core/IAtom
|
||||||
|
|
||||||
|
cljs.core/IEquiv
|
||||||
|
(-equiv [o other] (identical? o other))
|
||||||
|
|
||||||
|
cljs.core/IDeref
|
||||||
|
(-deref [this]
|
||||||
|
(register-dep this)
|
||||||
|
state)
|
||||||
|
|
||||||
|
IMeta
|
||||||
|
(-meta [_] meta)
|
||||||
|
|
||||||
|
IPrintWithWriter
|
||||||
|
(-pr-writer [a writer opts]
|
||||||
|
(-write writer "#<Cursor: ")
|
||||||
|
(pr-writer state writer opts)
|
||||||
|
(-write writer ">"))
|
||||||
|
|
||||||
|
IWatchable
|
||||||
|
(-notify-watches [this oldval newval]
|
||||||
|
(doseq [[key f] watches]
|
||||||
|
(f key this oldval newval)))
|
||||||
|
(-add-watch [this key f]
|
||||||
|
(set! (.-watches this) (assoc watches key f))
|
||||||
|
this)
|
||||||
|
(-remove-watch [this key]
|
||||||
|
(set! (.-watches this) (dissoc watches key)))
|
||||||
|
|
||||||
|
IHash
|
||||||
|
(-hash [this] (goog/getUid this))
|
||||||
|
|
||||||
|
IInvalidates
|
||||||
|
(-notify-invalidation-watches [this]
|
||||||
|
(doseq [[key f] invalidation-watches]
|
||||||
|
(f key this)))
|
||||||
|
(-add-invalidation-watch [this key f]
|
||||||
|
(set! (.-invalidation-watches this) (assoc invalidation-watches key f))
|
||||||
|
this)
|
||||||
|
(-remove-invalidation-watch [this key]
|
||||||
|
(set! (.-invalidation-watches this) (dissoc invalidation-watches key)))
|
||||||
|
|
||||||
|
IReset
|
||||||
|
(-reset! [a new-value]
|
||||||
|
(let [old-value (.-state a)]
|
||||||
|
(when (not= old-value new-value)
|
||||||
|
(swap! ref assoc-in path new-value)
|
||||||
|
(force-update-state cursor old-value new-value))))
|
||||||
|
|
||||||
|
ISwap
|
||||||
|
(-swap! [a f]
|
||||||
|
(do-update-state a (get-in (swap! ref update-in path f) path)))
|
||||||
|
(-swap! [a f x]
|
||||||
|
(do-update-state a (get-in (swap! ref update-in path f x) path)))
|
||||||
|
(-swap! [a f x y]
|
||||||
|
(do-update-state a (get-in (swap! ref update-in path f x y) path)))
|
||||||
|
(-swap! [a f x y more]
|
||||||
|
(do-update-state a (get-in (apply swap! ref update-in path f x y more) path))))
|
||||||
|
|
||||||
|
(defn cursor [ref korks]
|
||||||
|
(let [path (if (keyword? korks) [korks] korks)
|
||||||
|
cursor (Cursor. ref path nil nil nil nil)]
|
||||||
|
(add-watch ref cursor
|
||||||
|
(fn [_ _ old-value new-value]
|
||||||
|
(do-update-state cursor (get-in new-value path))))
|
||||||
|
(set! (.-state cursor) (get-in @ref path))
|
||||||
|
cursor))
|
|
@ -1,40 +1,38 @@
|
||||||
(ns freactive.experimental)
|
(ns freactive.experimental)
|
||||||
|
|
||||||
(defrecord ObservableCollection [state id-key])
|
(deftype ObservableCollection [state auto-key observers])
|
||||||
|
|
||||||
(declare do-txs)
|
(declare do-txs)
|
||||||
|
|
||||||
(defn- do-tx [state tx id-key]
|
(defn- do-tx [state tx auto-key]
|
||||||
(cond
|
(cond
|
||||||
(map? tx)
|
(map? tx)
|
||||||
(let [id (id-key tx)]
|
(let [id (auto-key)]
|
||||||
[(assoc state id tx) [id tx]])
|
[(assoc state id tx) [id tx]])
|
||||||
|
|
||||||
(sequential? tx)
|
(sequential? tx)
|
||||||
(let [[id op & args] tx]
|
(let [[id op & args] tx]
|
||||||
(cond
|
(cond
|
||||||
(sequential? id)
|
(sequential? id)
|
||||||
(do-txs state tx id-key)
|
(do-txs state tx auto-key)
|
||||||
|
|
||||||
(map? op)
|
(map? op)
|
||||||
(let [op (assoc op id-key id)]
|
[(assoc state id op) [id op]]
|
||||||
[(assoc state id op) [id op]])
|
|
||||||
|
|
||||||
(nil? op)
|
(nil? op)
|
||||||
[(dissoc state id) [id nil]]
|
[(dissoc state id) [id nil]]
|
||||||
|
|
||||||
(ifn? op)
|
(ifn? op)
|
||||||
(let [cur (get state id)
|
(let [cur (get state id)
|
||||||
res (apply op cur args)
|
res (apply op cur args)]
|
||||||
res (assoc res id-key id)]
|
|
||||||
[(assoc state id res) [id res]])))))
|
[(assoc state id res) [id res]])))))
|
||||||
|
|
||||||
(defn- do-txs [state txs id-key]
|
(defn- do-txs [state txs auto-key]
|
||||||
(loop [state state
|
(loop [state state
|
||||||
txs-res []
|
txs-res []
|
||||||
[tx & txs] txs]
|
[tx & txs] txs]
|
||||||
(if tx
|
(if tx
|
||||||
(let [[state tx-res] (do-tx state tx id-key)
|
(let [[state tx-res] (do-tx state tx auto-key)
|
||||||
txs-res (if (sequential? (first tx-res))
|
txs-res (if (sequential? (first tx-res))
|
||||||
(concat txs-res tx-res)
|
(concat txs-res tx-res)
|
||||||
(conj txs-res tx-res))]
|
(conj txs-res tx-res))]
|
||||||
|
@ -45,14 +43,15 @@
|
||||||
(compare-and-set! atomic old-state new-state))
|
(compare-and-set! atomic old-state new-state))
|
||||||
|
|
||||||
(defn- notify-coll [coll txs-res]
|
(defn- notify-coll [coll txs-res]
|
||||||
txs-res)
|
(doseq [[k f] (.-observers coll)]
|
||||||
|
(f k coll txs-res)))
|
||||||
|
|
||||||
(defn transact!* [coll tx-data]
|
(defn transact!* [coll tx-data]
|
||||||
(let [id-key (.-id-key coll)
|
(let [auto-key (.-auto-key coll)
|
||||||
state (.-state coll)]
|
state (.-state coll)]
|
||||||
(loop []
|
(loop []
|
||||||
(let [cur-state @state
|
(let [cur-state @state
|
||||||
[new-state txs-res] (do-txs cur-state tx-data id-key)]
|
[new-state txs-res] (do-txs cur-state tx-data auto-key)]
|
||||||
(if (do-cas! state cur-state new-state)
|
(if (do-cas! state cur-state new-state)
|
||||||
(notify-coll coll txs-res)
|
(notify-coll coll txs-res)
|
||||||
(recur))))))
|
(recur))))))
|
||||||
|
@ -61,7 +60,7 @@
|
||||||
(let [fst (first tx-data)]
|
(let [fst (first tx-data)]
|
||||||
(cond
|
(cond
|
||||||
(or (keyword? fst) (integer? fst) (string? fst))
|
(or (keyword? fst) (integer? fst) (string? fst))
|
||||||
(transact coll [tx-data])
|
(transact!* coll [tx-data])
|
||||||
|
|
||||||
:default
|
:default
|
||||||
(apply transact!* coll tx-data))))
|
(apply transact!* coll tx-data))))
|
||||||
|
@ -77,13 +76,26 @@
|
||||||
;; (transact! coll [0 assoc :a 1] [1 assoc :b 2])
|
;; (transact! coll [0 assoc :a 1] [1 assoc :b 2])
|
||||||
;; (transact! coll [[0 assoc :a 1] [1 assoc :b 2]])
|
;; (transact! coll [[0 assoc :a 1] [1 assoc :b 2]])
|
||||||
|
|
||||||
(defn observable-coll
|
(defn observable-collection
|
||||||
([atomic & {:keys [id-key]
|
([init & {:keys [auto-inc]}]
|
||||||
:or {id-key :id}}]
|
(let [init
|
||||||
(ObservableCollection. atomic id-key)))
|
(cond
|
||||||
|
(satisfies? cljs.core/IDeref init)
|
||||||
|
init
|
||||||
|
|
||||||
(defn observe-coll [coll key f])
|
(map? init)
|
||||||
|
(atom init)
|
||||||
|
|
||||||
|
(sequential? init)
|
||||||
|
(atom (zipmap (range) init))
|
||||||
|
|
||||||
|
:default
|
||||||
|
(atom {}))]
|
||||||
|
(ObservableCollection. init
|
||||||
|
(when auto-inc
|
||||||
|
(fn [] (count @init)))
|
||||||
|
nil))))
|
||||||
|
|
||||||
|
(defn observe-changes [coll key f]
|
||||||
|
(set! (.-observers coll) (assoc (.-observers coll) key f)))
|
||||||
|
|
||||||
(defn cursor
|
|
||||||
([atomic])
|
|
||||||
([atomic korks]))
|
|
||||||
|
|
|
@ -1,7 +1,50 @@
|
||||||
(ns freactive.experimental.dom
|
(ns freactive.experimental.dom
|
||||||
|
(:require-macros
|
||||||
|
[freactive.core :refer [rx]])
|
||||||
(:require
|
(:require
|
||||||
[freactive.core :as r]))
|
[freactive.core :as r]))
|
||||||
|
|
||||||
|
(defprotocol IElement
|
||||||
|
(-get-element-spec [this])
|
||||||
|
(-get-dom-node [this])
|
||||||
|
(-set-dom-node [this nide])
|
||||||
|
(-get-transition [this transition-name])
|
||||||
|
(-set-transitions [this transitions]))
|
||||||
|
|
||||||
|
(deftype Element [elem-spec dom-node transitions]
|
||||||
|
IElement
|
||||||
|
(-get-element-spec [_] elem-spec)
|
||||||
|
(-get-dom-node [_] dom-node)
|
||||||
|
(-set-dom-node [this node]
|
||||||
|
(set! (.-dom-node this) node))
|
||||||
|
(-get-transition [_ transition-name]
|
||||||
|
(get transitions transition-name))
|
||||||
|
(-set-transitions [this transitions]
|
||||||
|
(set! (.-transitions this) transitions)))
|
||||||
|
|
||||||
|
(defn- as-element [elem-spec]
|
||||||
|
(if (satisfies? IElement elem-spec)
|
||||||
|
elem-spec
|
||||||
|
(Element. elem-spec nil nil)))
|
||||||
|
|
||||||
|
(deftype DerefTransitionsWrapper [ref transitions])
|
||||||
|
|
||||||
|
(defn with-transitions [elem & {:as transitions}]
|
||||||
|
(cond
|
||||||
|
(or (sequential? elem) (string? elem))
|
||||||
|
(Element. elem nil transitions)
|
||||||
|
|
||||||
|
(satisfies? IDeref elem)
|
||||||
|
(DerefTransitionsWrapper. elem transitions)
|
||||||
|
|
||||||
|
(satisfies? IElement elem)
|
||||||
|
(do
|
||||||
|
(-set-transitions elem transitions)
|
||||||
|
elem)
|
||||||
|
|
||||||
|
:default
|
||||||
|
(Element. elem nil transitions)))
|
||||||
|
|
||||||
(defn request-animation-frame [f]
|
(defn request-animation-frame [f]
|
||||||
(.requestAnimationFrame js/window f))
|
(.requestAnimationFrame js/window f))
|
||||||
|
|
||||||
|
@ -22,15 +65,15 @@
|
||||||
(r/add-invalidation-watch ref key on-value-ref-invalidated)
|
(r/add-invalidation-watch ref key on-value-ref-invalidated)
|
||||||
(set-fn element attr-name @ref))))))
|
(set-fn element attr-name @ref))))))
|
||||||
|
|
||||||
(defn- bind-style-prop! [element attr-name attr-value]
|
(defn bind-style-prop! [element attr-name attr-value]
|
||||||
(if (satisfies? cljs.core/IDeref attr-value)
|
(if (satisfies? cljs.core/IDeref attr-value)
|
||||||
((on-value-ref-invalidated* set-style-prop!) attr-value [element attr-name])
|
((on-value-ref-invalidated* set-style-prop!) attr-value [element attr-name])
|
||||||
(set-style-prop! element attr-name attr-value)))
|
(set-style-prop! element attr-name attr-value)))
|
||||||
|
|
||||||
(defn- listen! [element evt-name handler]
|
(defn listen! [element evt-name handler]
|
||||||
(.addEventListener element evt-name handler))
|
(.addEventListener element evt-name handler))
|
||||||
|
|
||||||
(defn- bind-attr! [element attr-name attr-value]
|
(defn bind-attr! [element attr-name attr-value]
|
||||||
(let [attr-name (name attr-name)]
|
(let [attr-name (name attr-name)]
|
||||||
(cond
|
(cond
|
||||||
(= "style" attr-name)
|
(= "style" attr-name)
|
||||||
|
@ -45,73 +88,125 @@
|
||||||
:default
|
:default
|
||||||
(if (satisfies? cljs.core/IDeref attr-value)
|
(if (satisfies? cljs.core/IDeref attr-value)
|
||||||
((on-value-ref-invalidated* set-attr!) attr-value [element attr-name])
|
((on-value-ref-invalidated* set-attr!) attr-value [element attr-name])
|
||||||
(set-attr! element attr-name attr-value)))))
|
))))
|
||||||
|
|
||||||
(defn- create-elem [kw]
|
(defn- create-elem [kw]
|
||||||
(.createElement js/document (name kw)))
|
(.createElement js/document (name kw)))
|
||||||
|
|
||||||
(declare build)
|
(declare build)
|
||||||
|
|
||||||
(defn- convert-child [child]
|
(defn- replace-child [parent new-elem cur-elem]
|
||||||
|
(if (and
|
||||||
|
cur-elem
|
||||||
|
(string? new-elem)
|
||||||
|
(= (.-nodeType cur-elem) 3))
|
||||||
|
(set! (.-textContent cur-elem) new-elem)
|
||||||
|
(let [new-elem (as-element new-elem)
|
||||||
|
new-node (build-node (-get-element-spec new-elem))
|
||||||
|
cur-node (when cur-elem (-get-dom-node cur-elem))]
|
||||||
|
(-set-dom-node new-elem new-node)
|
||||||
|
(let [parent (if (satisfies? IElement parent)
|
||||||
|
(-get-dom-node parent)
|
||||||
|
parent)]
|
||||||
|
(if cur-node
|
||||||
|
(.replaceChild parent new-node cur-node)
|
||||||
|
(.appendChild parent new-node)))
|
||||||
|
new-elem)))
|
||||||
|
|
||||||
|
(defn- do-show-element [parent new-elem cur-elem show]
|
||||||
|
(let [new-elem (replace-child parent new-elem cur-elem)]
|
||||||
|
(when-let [show (or show (-get-transition new-elem :show))]
|
||||||
|
(show new-elem))
|
||||||
|
new-elem))
|
||||||
|
|
||||||
|
(defn- transition-element
|
||||||
|
([parent new-elem]
|
||||||
|
(transition-element parent new-elem nil nil nil))
|
||||||
|
([parent new-elem {:keys [hide show] :as transitions}]
|
||||||
|
(transition-element parent new-elem nil hide show))
|
||||||
|
([parent new-elem cur-elem hide show]
|
||||||
|
(if cur-elem
|
||||||
|
(if-let [hide (or hide (-get-transition cur-elem :hide))]
|
||||||
|
(hide cur-elem
|
||||||
|
(do-show-element parent new-elem cur-elem show))
|
||||||
|
(do-show-element parent new-elem cur-elem show))
|
||||||
|
(do-show-element parent new-elem cur-elem show))))
|
||||||
|
|
||||||
|
(defn on-child-ref-invalidated* [parent [add-watch* remove-watch*]
|
||||||
|
{:keys [hide show] :as transitions}]
|
||||||
|
(fn on-child-ref-invalidated
|
||||||
|
([key child-ref _ _]
|
||||||
|
(on-child-ref-invalidated key child-ref))
|
||||||
|
([cur-elem child-ref]
|
||||||
|
(remove-watch* child-ref cur-elem)
|
||||||
|
(request-animation-frame
|
||||||
|
(fn [_]
|
||||||
|
(add-watch* child-ref cur-elem on-child-ref-invalidated)
|
||||||
|
(let [new-elem @child-ref
|
||||||
|
cur @cur-elem]
|
||||||
|
(when (or (not cur) (not= (-get-element-spec cur) new-elem))
|
||||||
|
(reset! cur-elem
|
||||||
|
(transition-element parent new-elem cur hide show)))))))))
|
||||||
|
|
||||||
|
(defn- append-deref-child
|
||||||
|
[parent child transitions]
|
||||||
|
(if-let [watch-fns
|
||||||
|
(cond
|
||||||
|
(satisfies? freactive.core/IInvalidates child)
|
||||||
|
[r/add-invalidation-watch r/remove-invalidation-watch]
|
||||||
|
|
||||||
|
(satisfies? cljs.core/IWatchable child)
|
||||||
|
[add-watch remove-watch])]
|
||||||
|
((on-child-ref-invalidated* parent watch-fns transitions) (atom nil) child)
|
||||||
|
(transition-element parent @child transitions)))
|
||||||
|
|
||||||
|
(defn append-child! [parent child]
|
||||||
(cond
|
(cond
|
||||||
(string? child)
|
(instance? DerefTransitionsWrapper child)
|
||||||
(.createTextNode js/document child)
|
(append-deref-child parent (.-ref child) (.-transitions child))
|
||||||
|
|
||||||
|
(satisfies? cljs.core/IDeref child)
|
||||||
|
(append-deref-child parent child nil)
|
||||||
|
|
||||||
:default
|
:default
|
||||||
child))
|
(transition-element parent child)))
|
||||||
|
|
||||||
(defn- append-child!* [parent child]
|
|
||||||
(let [child (convert-child child)]
|
|
||||||
(.appendChild parent child)
|
|
||||||
child))
|
|
||||||
|
|
||||||
(defn- replace-child!* [parent new-child old-child]
|
|
||||||
(let [new-child (convert-child new-child)]
|
|
||||||
(.replaceChild parent new-child old-child)
|
|
||||||
new-child))
|
|
||||||
|
|
||||||
(defn on-child-ref-invalidated* [parent]
|
|
||||||
(fn on-child-ref-invalidated
|
|
||||||
[cur-elem child-ref]
|
|
||||||
(r/remove-invalidation-watch child-ref cur-elem)
|
|
||||||
(request-animation-frame
|
|
||||||
(fn [_]
|
|
||||||
(r/add-invalidation-watch child-ref cur-elem on-child-ref-invalidated)
|
|
||||||
(let [new-elem @child-ref
|
|
||||||
cur @cur-elem]
|
|
||||||
(reset! cur-elem
|
|
||||||
(if cur
|
|
||||||
(replace-child!* parent new-elem cur)
|
|
||||||
(append-child!* parent new-elem))))))))
|
|
||||||
|
|
||||||
(defn- append-child! [parent child]
|
|
||||||
(if
|
|
||||||
(satisfies? cljs.core/IDeref child)
|
|
||||||
((on-child-ref-invalidated* parent) (atom nil) child)
|
|
||||||
|
|
||||||
(append-child!* parent child)))
|
|
||||||
|
|
||||||
(defn- append-children! [elem children]
|
(defn- append-children! [elem children]
|
||||||
(doseq [ch children]
|
(doseq [ch children]
|
||||||
(if (sequential? ch)
|
(if (sequential? ch)
|
||||||
(if (keyword? (first ch))
|
(if (keyword? (first ch))
|
||||||
(append-child! elem (build ch))
|
(append-child! elem ch)
|
||||||
(append-children! elem ch))
|
(append-children! elem ch))
|
||||||
(append-child! elem ch))))
|
(append-child! elem ch))))
|
||||||
|
|
||||||
(defn build [elem-def]
|
(defn build-node [elem-def]
|
||||||
(let [elem (create-elem (first elem-def))
|
(if (string? elem-def)
|
||||||
attrs? (second elem-def)
|
(.createTextNode js/document elem-def)
|
||||||
attrs (when (map? attrs?) attrs?)
|
(let [elem (create-elem (first elem-def))
|
||||||
children (if attrs (nnext elem-def) (next elem-def))]
|
attrs? (second elem-def)
|
||||||
(doseq [[k v] attrs]
|
attrs (when (map? attrs?) attrs?)
|
||||||
(bind-attr! elem k v))
|
children (if attrs (nnext elem-def) (next elem-def))]
|
||||||
(when children
|
(doseq [[k v] attrs]
|
||||||
(append-children! elem children))
|
(bind-attr! elem k v))
|
||||||
elem))
|
(when children
|
||||||
|
(append-children! elem children))
|
||||||
|
elem)))
|
||||||
|
|
||||||
|
(defn- get-body []
|
||||||
|
(aget (.getElementsByTagName js/document "body") 0))
|
||||||
|
|
||||||
(defn mount! [dom-element child]
|
(defn mount! [dom-element child]
|
||||||
(append-child! dom-element child))
|
(append-child! dom-element child))
|
||||||
|
|
||||||
(defn- get-body []
|
;(defn create-raw [elem-def]
|
||||||
(aget (.getElementsByTagName js/document "body") 0))
|
; (let [elem-def
|
||||||
|
; (cond
|
||||||
|
; (keyword? elem-def)
|
||||||
|
; [elem-def]
|
||||||
|
;
|
||||||
|
; :default
|
||||||
|
; elem-def)
|
||||||
|
; elem (as-element elem-def)
|
||||||
|
; node (build-node (-get-element-spec elem))]
|
||||||
|
; (-set-dom-node elem node)
|
||||||
|
; elem))
|
||||||
|
|
56
src/clojure/freactive/experimental/items_view.cljs
Normal file
56
src/clojure/freactive/experimental/items_view.cljs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
(ns freactive.experimental.items-view
|
||||||
|
(:refer-clojure :exclude [atom])
|
||||||
|
(:require
|
||||||
|
[freactive.core :refer [atom]]
|
||||||
|
[freactive.experimental.dom :as dom]
|
||||||
|
[freactive.experimental :refer [observable-collection
|
||||||
|
observe-changes transact!]]))
|
||||||
|
|
||||||
|
(deftype ItemsView [elem-spec dom-node transitions template-fn coll]
|
||||||
|
freactive.experimental.dom/IElement
|
||||||
|
(-get-element-spec [_] elem-spec)
|
||||||
|
(-get-dom-node [_] dom-node)
|
||||||
|
(-set-dom-node [this node]
|
||||||
|
(set! (.-dom-node this) node))
|
||||||
|
(-get-transition [_ transition-name]
|
||||||
|
(get transitions transition-name))
|
||||||
|
(-set-transitions [this transitions]
|
||||||
|
(set! (.-transitions this) transitions)))
|
||||||
|
|
||||||
|
(defn items-view
|
||||||
|
[container template-fn items]
|
||||||
|
(let [coll
|
||||||
|
(cond
|
||||||
|
(instance? freactive.experimental/ObservableCollection items)
|
||||||
|
items
|
||||||
|
|
||||||
|
:default
|
||||||
|
(observable-collection items :auto-inc true))
|
||||||
|
|
||||||
|
container
|
||||||
|
(cond
|
||||||
|
(keyword? container)
|
||||||
|
[container]
|
||||||
|
|
||||||
|
:default
|
||||||
|
container)
|
||||||
|
|
||||||
|
view (ItemsView. container nil nil template-fn coll)
|
||||||
|
|
||||||
|
update-fn
|
||||||
|
(fn [view coll changes]
|
||||||
|
(doseq [[k v] changes]
|
||||||
|
(dom/append-child! view (template-fn (atom v)))))]
|
||||||
|
|
||||||
|
(dom/with-transitions
|
||||||
|
view
|
||||||
|
:show
|
||||||
|
(fn on-mount [view]
|
||||||
|
(println "coll" coll)
|
||||||
|
(update-fn view coll @(.-state coll))
|
||||||
|
(observe-changes coll view update-fn)))))
|
||||||
|
|
||||||
|
|
||||||
|
(def c0 (observable-collection {:a "abc"}))
|
||||||
|
|
||||||
|
(dom/mount! dom/root (items-view [:ul] (fn [x] [:li @x]) c0))
|
|
@ -1,7 +1,7 @@
|
||||||
(ns freactive.core-test
|
(ns freactive.core-test
|
||||||
(:refer-clojure :exclude [atom])
|
(:refer-clojure :exclude [atom])
|
||||||
(:require
|
(:require
|
||||||
[freactive.core :refer [atom rx*]]
|
[freactive.core :refer [atom cursor rx*]]
|
||||||
[cemerick.cljs.test :refer-macros [deftest is]]))
|
[cemerick.cljs.test :refer-macros [deftest is]]))
|
||||||
|
|
||||||
(deftest rx-test1
|
(deftest rx-test1
|
||||||
|
@ -10,3 +10,15 @@
|
||||||
(is (= 1 @r1))
|
(is (= 1 @r1))
|
||||||
(swap! r0 inc)
|
(swap! r0 inc)
|
||||||
(is (= 2 @r1))))
|
(is (= 2 @r1))))
|
||||||
|
|
||||||
|
(deftest cursor-test
|
||||||
|
(let [a (atom {:a {:b 2}})
|
||||||
|
b (cursor a :a)
|
||||||
|
c (rx* (fn [] (inc (:b @b))))]
|
||||||
|
(is (= (:b @b) 2))
|
||||||
|
(swap! a update-in [:a :b] inc)
|
||||||
|
(is (= (:b @b) 3))
|
||||||
|
(is (= @c 4))
|
||||||
|
(swap! b update-in [:b] inc)
|
||||||
|
(is (:b @b 4))
|
||||||
|
(is (= @c 5))))
|
||||||
|
|
Loading…
Reference in a new issue