Refactored a lot of dom.cljs to support inserts properly, made ref transitions based on alter-meta! and added :binding-initialized and :binding-disposed callbacks. Played with the items view a little.
This commit is contained in:
parent
cf678507b6
commit
0e7134a5d7
4 changed files with 207 additions and 110 deletions
|
@ -8,6 +8,7 @@
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script src="js/compiled/out/goog/base.js" type="text/javascript"></script>
|
<script src="js/compiled/out/goog/base.js" type="text/javascript"></script>
|
||||||
<script src="js/compiled/app.js" type="text/javascript"></script>
|
<script src="js/compiled/app.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">goog.require("freactive.dom_perf");</script>
|
<!--<script type="text/javascript">goog.require("freactive.dom_perf");</script>-->
|
||||||
|
<script type="text/javascript">goog.require("freactive.items_view_test");</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -7,15 +7,14 @@
|
||||||
|
|
||||||
(defonce ^:private auto-node-id 0)
|
(defonce ^:private auto-node-id 0)
|
||||||
|
|
||||||
;(defonce ^:private element-state-lookup {})
|
|
||||||
(defonce ^:private element-state-lookup #js {})
|
(defonce ^:private element-state-lookup #js {})
|
||||||
|
|
||||||
(defprotocol IElementSpec
|
(defprotocol IElementSpec
|
||||||
(-get-virtual-dom [x]))
|
(-get-virtual-dom [x]))
|
||||||
|
|
||||||
(defrecord ElementSpec [spec]
|
;(defrecord ElementSpec [spec]
|
||||||
IElementSpec
|
; IElementSpec
|
||||||
(-get-virtual-dom [x] spec))
|
; (-get-virtual-dom [x] spec))
|
||||||
|
|
||||||
(defn- dom-node? [x]
|
(defn- dom-node? [x]
|
||||||
(> (.-nodeType x) 0))
|
(> (.-nodeType x) 0))
|
||||||
|
@ -36,6 +35,12 @@
|
||||||
boolean
|
boolean
|
||||||
(-get-virtual-dom [x] (str x)))
|
(-get-virtual-dom [x] (str x)))
|
||||||
|
|
||||||
|
(defn- get-element-spec [x]
|
||||||
|
(if (dom-node? x)
|
||||||
|
(when-let [state (get-element-state x)]
|
||||||
|
(.-element-spec state))
|
||||||
|
x))
|
||||||
|
|
||||||
(defn- get-virtual-dom [x]
|
(defn- get-virtual-dom [x]
|
||||||
(if x
|
(if x
|
||||||
(cond
|
(cond
|
||||||
|
@ -54,9 +59,6 @@
|
||||||
;; nil values treated as empty "placeholder" text nodes
|
;; nil values treated as empty "placeholder" text nodes
|
||||||
""))
|
""))
|
||||||
|
|
||||||
(defn- reset-element-spec! [dom-node spec]
|
|
||||||
(set! (.-element-spec (get-element-state dom-node)) spec))
|
|
||||||
|
|
||||||
(deftype ElementState [id disposed element-spec child-states])
|
(deftype ElementState [id disposed element-spec child-states])
|
||||||
|
|
||||||
(declare set-attr!)
|
(declare set-attr!)
|
||||||
|
@ -84,14 +86,10 @@
|
||||||
(defn- unregister-from-parent-state [parent-state child-key]
|
(defn- unregister-from-parent-state [parent-state child-key]
|
||||||
;;(set! (.-child-states parent-state) (dissoc (.-child-states parent-state) child))
|
;;(set! (.-child-states parent-state) (dissoc (.-child-states parent-state) child))
|
||||||
(when-let [child-states (.-child-states parent-state)]
|
(when-let [child-states (.-child-states parent-state)]
|
||||||
(js-delete child-states child-key))
|
(js-delete child-states child-key)))
|
||||||
)
|
|
||||||
|
|
||||||
(defn- get-element-spec [x]
|
(defn- reset-element-spec! [dom-node spec]
|
||||||
(if (dom-node? x)
|
(set! (.-element-spec (get-element-state dom-node)) spec))
|
||||||
(when-let [state (get-element-state x)]
|
|
||||||
(.-element-spec state))
|
|
||||||
x))
|
|
||||||
|
|
||||||
(defprotocol IRemove
|
(defprotocol IRemove
|
||||||
(-remove! [x]))
|
(-remove! [x]))
|
||||||
|
@ -130,46 +128,48 @@
|
||||||
|
|
||||||
(defn remove! [x]
|
(defn remove! [x]
|
||||||
(if (dom-node? x)
|
(if (dom-node? x)
|
||||||
(remove-dom-node x)
|
(if-let [node-detaching (get-transition x :node-detaching)]
|
||||||
|
(node-detaching x (fn [] (remove-dom-node x)))
|
||||||
|
(remove-dom-node x))
|
||||||
(-remove! x)))
|
(-remove! x)))
|
||||||
|
|
||||||
;; ## Defining Transitions
|
;; ## Defining Transitions
|
||||||
|
|
||||||
(defn- wrap-element-spec [elem-spec]
|
;(defn- wrap-element-spec [elem-spec]
|
||||||
(if (string? elem-spec)
|
; (if (string? elem-spec)
|
||||||
(ElementSpec. elem-spec)
|
; (ElementSpec. elem-spec)
|
||||||
elem-spec))
|
; elem-spec))
|
||||||
|
|
||||||
(defn with-transitions [elem-spec transitions]
|
(defn with-transitions [elem-spec transitions]
|
||||||
(if (satisfies? IDeref elem-spec)
|
(if (satisfies? IDeref elem-spec)
|
||||||
(rx (with-transitions @elem-spec transitions))
|
(alter-meta! elem-spec merge transitions)
|
||||||
(vary-meta (wrap-element-spec elem-spec) merge transitions)))
|
(vary-meta elem-spec merge transitions)))
|
||||||
|
|
||||||
(defn- exec-transition [node transition-name callback]
|
(defn- exec-transition [node transition-name callback]
|
||||||
(if-let [transition (get-transition node transition-name)]
|
(if-let [transition (get-transition node transition-name)]
|
||||||
(transition node callback)
|
(transition node callback)
|
||||||
(when callback (callback))))
|
(when callback (callback))))
|
||||||
|
;
|
||||||
(defn- chain-transition [elem-spec transition-name transition-fn chain-fn]
|
;(defn- chain-transition [elem-spec transition-name transition-fn chain-fn]
|
||||||
(if (satisfies? IDeref elem-spec)
|
; (if (satisfies? IDeref elem-spec)
|
||||||
(rx (chain-transition @elem-spec transition-name transition-fn chain-fn))
|
; (rx (chain-transition @elem-spec transition-name transition-fn chain-fn))
|
||||||
(let [cur-transition-fn (get-transition elem-spec transition-name)
|
; (let [cur-transition-fn (get-transition elem-spec transition-name)
|
||||||
transition-fn (if cur-transition-fn
|
; transition-fn (if cur-transition-fn
|
||||||
(chain-fn cur-transition-fn transition-fn)
|
; (chain-fn cur-transition-fn transition-fn)
|
||||||
transition-fn)]
|
; transition-fn)]
|
||||||
(with-transitions elem-spec {transition-name transition-fn}))))
|
; (with-transitions elem-spec {transition-name transition-fn}))))
|
||||||
|
;
|
||||||
(defn prepend-transition [elem-spec transition-name transition-fn]
|
;(defn prepend-transition [elem-spec transition-name transition-fn]
|
||||||
(chain-transition elem-spec transition-name transition-fn
|
; (chain-transition elem-spec transition-name transition-fn
|
||||||
(fn [cur-tx new-tx]
|
; (fn [cur-tx new-tx]
|
||||||
(fn [elem on-complete]
|
; (fn [elem on-complete]
|
||||||
(new-tx elem (fn [elem _] (cur-tx elem on-complete)))))) )
|
; (new-tx elem (fn [elem _] (cur-tx elem on-complete)))))) )
|
||||||
|
;
|
||||||
(defn append-transition [elem-spec transition-name transition-fn]
|
;(defn append-transition [elem-spec transition-name transition-fn]
|
||||||
(chain-transition elem-spec transition-name transition-fn
|
; (chain-transition elem-spec transition-name transition-fn
|
||||||
(fn [cur-tx new-tx]
|
; (fn [cur-tx new-tx]
|
||||||
(fn [elem on-complete]
|
; (fn [elem on-complete]
|
||||||
(cur-tx elem (fn [elem _] (new-tx elem on-complete)))))) )
|
; (cur-tx elem (fn [elem _] (new-tx elem on-complete)))))) )
|
||||||
|
|
||||||
;; ## Polyfills
|
;; ## Polyfills
|
||||||
|
|
||||||
|
@ -229,12 +229,16 @@
|
||||||
(.removeAttribute elem attr-name))
|
(.removeAttribute elem attr-name))
|
||||||
|
|
||||||
(defn- set-style-prop! [elem prop-name prop-value]
|
(defn- set-style-prop! [elem prop-name prop-value]
|
||||||
(aset (.-style elem) prop-name (str prop-value)))
|
(aset (.-style elem)
|
||||||
|
prop-name
|
||||||
|
(if (.-substring prop-value)
|
||||||
|
prop-value
|
||||||
|
(.toString prop-value))))
|
||||||
|
|
||||||
(defn- remove-style-prop! [elem prop-name]
|
(defn- remove-style-prop! [elem prop-name]
|
||||||
(js-delete (.-style elem) prop-name))
|
(js-delete (.-style elem) prop-name))
|
||||||
|
|
||||||
(defn- on-value-ref-invalidated* [set-fn element state-prefix attr-name ref node-state]
|
(defn- bind-attr* [set-fn element state-prefix attr-name ref node-state]
|
||||||
(when-let [[add-watch* remove-watch*] (r/get-add-remove-watch* ref)]
|
(when-let [[add-watch* remove-watch*] (r/get-add-remove-watch* ref)]
|
||||||
(let [attr-state #js {:disposed false}
|
(let [attr-state #js {:disposed false}
|
||||||
key [element attr-name]
|
key [element attr-name]
|
||||||
|
@ -253,13 +257,14 @@
|
||||||
(register-with-parent-state node-state
|
(register-with-parent-state node-state
|
||||||
(str "-" state-prefix "." attr-name) attr-state)
|
(str "-" state-prefix "." attr-name) attr-state)
|
||||||
(add-watch* ref key f)))
|
(add-watch* ref key f)))
|
||||||
|
|
||||||
(set-fn @ref))
|
(set-fn @ref))
|
||||||
|
|
||||||
(defn- bind-style-prop! [element attr-name attr-value node-state]
|
(defn- bind-style-prop! [element attr-name attr-value node-state]
|
||||||
(let [setter (fn [v] (set-style-prop! element attr-name attr-value))]
|
(let [setter (fn [v]
|
||||||
|
(println "setting style" element attr-name v)
|
||||||
|
(set-style-prop! element attr-name v))]
|
||||||
(if (satisfies? cljs.core/IDeref attr-value)
|
(if (satisfies? cljs.core/IDeref attr-value)
|
||||||
(on-value-ref-invalidated* setter element "style" attr-name attr-value node-state)
|
(bind-attr* setter element "style" attr-name attr-value node-state)
|
||||||
(setter attr-value))))
|
(setter attr-value))))
|
||||||
|
|
||||||
(defn listen! [element evt-name handler]
|
(defn listen! [element evt-name handler]
|
||||||
|
@ -291,7 +296,7 @@
|
||||||
|
|
||||||
(defn- bind-prop-attr! [set-fn element attr-name attr-value node-state]
|
(defn- bind-prop-attr! [set-fn element attr-name attr-value node-state]
|
||||||
(if (satisfies? cljs.core/IDeref attr-value)
|
(if (satisfies? cljs.core/IDeref attr-value)
|
||||||
(on-value-ref-invalidated* set-fn element "attr" attr-name
|
(bind-attr* set-fn element "attr" attr-name
|
||||||
attr-value node-state)
|
attr-value node-state)
|
||||||
(set-fn attr-value)))
|
(set-fn attr-value)))
|
||||||
|
|
||||||
|
@ -323,7 +328,12 @@
|
||||||
(fn [cls] (set! (.-className element) cls))
|
(fn [cls] (set! (.-className element) cls))
|
||||||
|
|
||||||
:default
|
:default
|
||||||
(fn [attr-value] (.setAttribute element attr-name attr-value))))
|
(fn [attr-value]
|
||||||
|
(.setAttribute
|
||||||
|
element attr-name
|
||||||
|
(if (.-substring attr-value)
|
||||||
|
attr-value
|
||||||
|
(.toString attr-value))))))
|
||||||
|
|
||||||
(defn- bind-attr! [element attr-name attr-value node-state]
|
(defn- bind-attr! [element attr-name attr-value node-state]
|
||||||
(let [attr-name (name attr-name)]
|
(let [attr-name (name attr-name)]
|
||||||
|
@ -494,16 +504,22 @@
|
||||||
children)
|
children)
|
||||||
dom-vec)))
|
dom-vec)))
|
||||||
|
|
||||||
|
(defn- register-element-with-parent [parent new-elem]
|
||||||
|
(when-not (text-node? new-elem)
|
||||||
|
(when-let [parent-state (get-element-state parent)]
|
||||||
|
(let [state (get-element-state new-elem)]
|
||||||
|
(set! (.-parent-state state) parent-state)
|
||||||
|
(register-with-parent-state parent-state (get-node-id new-elem) state)))))
|
||||||
|
|
||||||
(defn- replace-node-completly [parent new-elem-spec cur-dom-node]
|
(defn- replace-node-completly [parent new-elem-spec cur-dom-node]
|
||||||
(let [new-elem (build-element new-elem-spec)]
|
(let [new-elem (build-element new-elem-spec)]
|
||||||
(.replaceChild parent new-elem cur-dom-node)
|
(register-element-with-parent parent new-elem)
|
||||||
(dispose-node cur-dom-node)
|
(.replaceChild parent new-elem cur-dom-node)
|
||||||
new-elem))
|
(dispose-node cur-dom-node)
|
||||||
|
new-elem))
|
||||||
|
|
||||||
(declare replace-child)
|
(declare replace-child)
|
||||||
|
|
||||||
(declare replace-or-append-child)
|
|
||||||
|
|
||||||
(declare append-children!)
|
(declare append-children!)
|
||||||
|
|
||||||
(defn- try-diff-subseq [parent cur-child new-children]
|
(defn- try-diff-subseq [parent cur-child new-children]
|
||||||
|
@ -570,47 +586,40 @@
|
||||||
(replace-node-completly parent new-elem-spec cur-dom-node))))
|
(replace-node-completly parent new-elem-spec cur-dom-node))))
|
||||||
(replace-node-completly parent new-elem-spec cur-dom-node)))))
|
(replace-node-completly parent new-elem-spec cur-dom-node)))))
|
||||||
|
|
||||||
|
(defn- insert-child [parent vdom before]
|
||||||
|
(let [new-elem (build-element vdom)]
|
||||||
|
(register-element-with-parent parent new-elem)
|
||||||
|
(.insertBefore parent new-elem before)
|
||||||
|
new-elem))
|
||||||
|
|
||||||
(defn- append-child [parent new-elem]
|
(defn- append-child [parent new-elem]
|
||||||
(let [new-elem (build-element new-elem)]
|
(let [new-elem (build-element new-elem)]
|
||||||
(.appendChild
|
(register-element-with-parent parent new-elem)
|
||||||
;(get-dom-node parent)
|
(.appendChild parent new-elem)
|
||||||
parent
|
|
||||||
new-elem)
|
|
||||||
new-elem))
|
new-elem))
|
||||||
|
|
||||||
(defn- register-element-with-parent [parent new-elem]
|
(defn- append-or-insert-child [parent new-elem before]
|
||||||
(when-not (text-node? new-elem)
|
(if before
|
||||||
(when-let [parent-state (get-element-state parent)]
|
(insert-child parent new-elem before)
|
||||||
(let [state (get-element-state new-elem)]
|
(append-child parent new-elem)))
|
||||||
(set! (.-parent-state state) parent-state)
|
|
||||||
(register-with-parent-state parent-state (get-node-id new-elem) state))))
|
|
||||||
)
|
|
||||||
|
|
||||||
(defn- replace-or-append-child [parent new-elem cur-elem top-level]
|
;(defn- do-show-element [parent new-elem nil]
|
||||||
(let [new-elem
|
; (when new-elem
|
||||||
(if cur-elem
|
; (let [show (get-transition new-elem :node-attached)
|
||||||
(replace-child parent new-elem cur-elem top-level)
|
; new-elem (replace-or-append-child parent new-elem cur-elem true)]
|
||||||
(append-child parent new-elem))]
|
; (when show
|
||||||
(register-element-with-parent parent new-elem)
|
; (show new-elem)
|
||||||
new-elem))
|
; new-elem)
|
||||||
|
; new-elem)))
|
||||||
|
|
||||||
(defn- do-show-element [parent new-elem cur-elem]
|
(defn- mount-element
|
||||||
(when new-elem
|
([parent new-elem before]
|
||||||
(let [show (get-transition new-elem :node-attached)
|
(let [show (get-transition new-elem :node-mounted)
|
||||||
new-elem (replace-or-append-child parent new-elem cur-elem true)]
|
new-elem (append-or-insert-child parent new-elem before)]
|
||||||
(when show
|
(when show
|
||||||
(show new-elem)
|
(show new-elem)
|
||||||
new-elem)
|
new-elem)
|
||||||
new-elem)))
|
new-elem)))
|
||||||
|
|
||||||
(defn- transition-element
|
|
||||||
([parent new-elem cur-elem]
|
|
||||||
(if cur-elem
|
|
||||||
(if-let [hide (get-transition cur-elem :node-detaching)]
|
|
||||||
(hide cur-elem
|
|
||||||
(do-show-element parent new-elem cur-elem))
|
|
||||||
(do-show-element parent new-elem cur-elem))
|
|
||||||
(do-show-element parent new-elem cur-elem))))
|
|
||||||
|
|
||||||
(defn- clear-children! [parent]
|
(defn- clear-children! [parent]
|
||||||
(let [dom-node parent
|
(let [dom-node parent
|
||||||
|
@ -650,7 +659,7 @@
|
||||||
(when-let [parent-state (get-element-state parent)]
|
(when-let [parent-state (get-element-state parent)]
|
||||||
(unregister-from-parent-state parent-state id))))
|
(unregister-from-parent-state parent-state id))))
|
||||||
|
|
||||||
(defn- append-deref-child [parent child-ref]
|
(defn- bind-child [parent child-ref before]
|
||||||
(if-let [[add-watch* remove-watch*] (r/get-add-remove-watch* child-ref)]
|
(if-let [[add-watch* remove-watch*] (r/get-add-remove-watch* child-ref)]
|
||||||
(let [state (ReactiveElement. nil parent nil false false false nil nil)
|
(let [state (ReactiveElement. nil parent nil false false false nil nil)
|
||||||
|
|
||||||
|
@ -660,7 +669,10 @@
|
||||||
(or (non-reactively @child-ref) ""))
|
(or (non-reactively @child-ref) ""))
|
||||||
|
|
||||||
show-new-elem (fn [new-elem cur]
|
show-new-elem (fn [new-elem cur]
|
||||||
(let [new-node (replace-or-append-child parent new-elem cur true)]
|
(let [new-node
|
||||||
|
(if cur
|
||||||
|
(replace-child parent new-elem cur true)
|
||||||
|
(append-or-insert-child parent new-elem before))]
|
||||||
(set! (.-cur-element state) new-node)
|
(set! (.-cur-element state) new-node)
|
||||||
(set! (.-updating state) false)
|
(set! (.-updating state) false)
|
||||||
(when (.-dirty state)
|
(when (.-dirty state)
|
||||||
|
@ -688,9 +700,7 @@
|
||||||
(get-new-elem)
|
(get-new-elem)
|
||||||
new-elem)]
|
new-elem)]
|
||||||
(show-new-elem new-elem cur))))))
|
(show-new-elem new-elem cur))))))
|
||||||
(show-new-elem new-elem cur)))
|
(show-new-elem new-elem cur))))))))
|
||||||
|
|
||||||
)))))
|
|
||||||
|
|
||||||
invalidate
|
invalidate
|
||||||
(fn on-child-ref-invalidated
|
(fn on-child-ref-invalidated
|
||||||
|
@ -703,26 +713,38 @@
|
||||||
(when-not (.-updating state)
|
(when-not (.-updating state)
|
||||||
(set! (.-updating state) true)
|
(set! (.-updating state) true)
|
||||||
(queue-animation animate)))))]
|
(queue-animation animate)))))]
|
||||||
|
|
||||||
(set! (.-animate state) animate)
|
(set! (.-animate state) animate)
|
||||||
(set! (.-invalidate state) invalidate)
|
(set! (.-invalidate state) invalidate)
|
||||||
(show-new-elem (get-new-elem) nil)
|
(when-let [binding-disposed (get (meta child-ref) :binding-disposed)]
|
||||||
;(set! (.-cur-element state)
|
(set! (.-disposed-callback state) binding-disposed))
|
||||||
; (transition-element parent (or (non-reactively @child-ref) [:span]) nil))
|
|
||||||
(when-let [parent-state (get-element-state parent)]
|
(when-let [parent-state (get-element-state parent)]
|
||||||
(register-with-parent-state parent-state "-reactive" state))
|
(register-with-parent-state parent-state "-reactive" state))
|
||||||
|
(when-let [binding-initialized (get (meta child-ref)
|
||||||
|
:binding-initialized)]
|
||||||
|
(binding-initialized))
|
||||||
|
(set! (.-updating state) false)
|
||||||
|
;(let [new-node (append-or-insert-child parent (get-new-elem) before)]
|
||||||
|
; (set! (.-cur-element state) new-node)
|
||||||
|
; (when-let [node-mounted (get-transition new-node :node-attached)]
|
||||||
|
; (node-mounted new-node))
|
||||||
|
; (when (.-dirty state)
|
||||||
|
; (queue-animation (.-animate state))))
|
||||||
|
(show-new-elem (get-new-elem) nil)
|
||||||
state)
|
state)
|
||||||
(transition-element parent @child-ref nil)))
|
(mount-element parent @child-ref before)))
|
||||||
|
|
||||||
;; Building Elements
|
;; Building Elements
|
||||||
|
|
||||||
(defn append-child! [parent child]
|
(defn insert-child! [parent child before]
|
||||||
(cond
|
(cond
|
||||||
(satisfies? IDeref child)
|
(satisfies? IDeref child)
|
||||||
(append-deref-child parent child)
|
(bind-child parent child before)
|
||||||
|
|
||||||
:default
|
:default
|
||||||
(transition-element parent child nil)))
|
(mount-element parent child before)))
|
||||||
|
|
||||||
|
(defn append-child! [parent child]
|
||||||
|
(insert-child! parent child nil))
|
||||||
|
|
||||||
(defn- append-children! [elem children]
|
(defn- append-children! [elem children]
|
||||||
(doseq [ch children]
|
(doseq [ch children]
|
||||||
|
@ -734,6 +756,7 @@
|
||||||
|
|
||||||
(defn build-element [elem-spec]
|
(defn build-element [elem-spec]
|
||||||
(let [virtual-dom (get-virtual-dom elem-spec)]
|
(let [virtual-dom (get-virtual-dom elem-spec)]
|
||||||
|
(println virtual-dom)
|
||||||
(cond
|
(cond
|
||||||
(string? virtual-dom)
|
(string? virtual-dom)
|
||||||
(.createTextNode js/document virtual-dom)
|
(.createTextNode js/document virtual-dom)
|
||||||
|
@ -752,6 +775,9 @@
|
||||||
(bind-attr! node k v state))
|
(bind-attr! node k v state))
|
||||||
(when children
|
(when children
|
||||||
(append-children! node children))
|
(append-children! node children))
|
||||||
|
(when-let [m (-meta virtual-dom)]
|
||||||
|
(when-let [node-created (get m :node-created)]
|
||||||
|
(node-created node)))
|
||||||
node))))
|
node))))
|
||||||
|
|
||||||
(defn mount! [element child]
|
(defn mount! [element child]
|
||||||
|
|
|
@ -14,12 +14,12 @@
|
||||||
(-reset-view [view])
|
(-reset-view [view])
|
||||||
(-set-view-range [view start end]))
|
(-set-view-range [view start end]))
|
||||||
|
|
||||||
(defrecord ItemsView [element coll]
|
(deftype ItemsView [element collection]
|
||||||
dom/IHasElement
|
dom/IElementSpec
|
||||||
(-get-element [_] element)
|
(-get-virtual-dom [_] element)
|
||||||
|
|
||||||
dom/IRemove
|
dom/IRemove
|
||||||
(-remove [_] (dom/-remove element)))
|
(-remove! [_] (dom/remove! element)))
|
||||||
|
|
||||||
(deftype ItemContainer [elem state])
|
(deftype ItemContainer [elem state])
|
||||||
|
|
||||||
|
@ -48,21 +48,21 @@
|
||||||
view (ItemsView. element coll)
|
view (ItemsView. element coll)
|
||||||
|
|
||||||
update-fn
|
update-fn
|
||||||
(fn [view coll changes]
|
(fn [view changes]
|
||||||
(doseq [[k v] changes]
|
(doseq [[k v] changes]
|
||||||
(let [elem-container (get @elem-mappings k)]
|
(let [elem-container (get @elem-mappings k)]
|
||||||
(if elem-container
|
(if elem-container
|
||||||
(if v
|
(if v
|
||||||
(reset! (.-state elem-container) v)
|
(reset! (.-state elem-container) v)
|
||||||
(do
|
(do
|
||||||
(dom/-remove (.-elem elem-container))
|
(dom/remove! (.-elem elem-container))
|
||||||
(swap! elem-mappings dissoc k)))
|
(swap! elem-mappings dissoc k)))
|
||||||
(when v
|
(when v
|
||||||
(let [state (atom v)
|
(let [state (atom v)
|
||||||
elem (dom/append-child! (.-element view) (template-fn state))]
|
elem (dom/append-child! (.-element view) (template-fn state))]
|
||||||
(swap! elem-mappings assoc k (ItemContainer. elem state))))))))]
|
(swap! elem-mappings assoc k (ItemContainer. elem state))))))))]
|
||||||
|
|
||||||
(update-fn view coll @(.-state coll))
|
(update-fn view @(.-state coll))
|
||||||
(observe-changes coll view update-fn)
|
(observe-changes coll view update-fn)
|
||||||
|
|
||||||
#_(dom/with-transitions
|
#_(dom/with-transitions
|
||||||
|
|
70
test/freactive/items_view_test.cljs
Normal file
70
test/freactive/items_view_test.cljs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
(ns freactive.items-view-test
|
||||||
|
(:refer-clojure :exclude [atom])
|
||||||
|
(:require [freactive.dom :as dom]
|
||||||
|
[freactive.core :refer [atom rx]]
|
||||||
|
[freactive.experimental.observable-collection :refer
|
||||||
|
[observable-collection transact!]]
|
||||||
|
[freactive.experimental.items-view :as items-view]
|
||||||
|
[figwheel.client :as fw]
|
||||||
|
[cljs.core.async :refer [chan put! <!]])
|
||||||
|
(:require-macros
|
||||||
|
[cljs.core.async.macros :refer [go go-loop]]
|
||||||
|
[freactive.macros :refer [rx]]))
|
||||||
|
|
||||||
|
(enable-console-print!)
|
||||||
|
|
||||||
|
(dom/enable-fps-instrumentation!)
|
||||||
|
|
||||||
|
(defn item-view [item]
|
||||||
|
(let [state (atom :viewing)
|
||||||
|
action-ch (chan)]
|
||||||
|
(go-loop []
|
||||||
|
(let [action (<! action-ch)]
|
||||||
|
(case @state
|
||||||
|
:viewing
|
||||||
|
(when (= action :edit)
|
||||||
|
(reset! state :editing))
|
||||||
|
:editing
|
||||||
|
(when (= action :commit)
|
||||||
|
(reset! state :viewing)))
|
||||||
|
(recur)))
|
||||||
|
[:li
|
||||||
|
(dom/with-transitions
|
||||||
|
[:input {:value @item :data-state @state
|
||||||
|
:on-keypress
|
||||||
|
(fn [e]
|
||||||
|
(when (= (.-keyCode e) 13)
|
||||||
|
(put! action-ch :commit)
|
||||||
|
(.preventDefault e)))
|
||||||
|
:on-changed
|
||||||
|
(fn [e] (reset! item (.. e -target -value)))
|
||||||
|
:style {:display
|
||||||
|
(rx
|
||||||
|
(if (= @state :editing)
|
||||||
|
""
|
||||||
|
"none"))}}]
|
||||||
|
{})
|
||||||
|
[:span
|
||||||
|
{:on-mousedown (fn [e] (put! action-ch :edit))
|
||||||
|
:style {:display
|
||||||
|
(rx
|
||||||
|
(if (= @state :viewing)
|
||||||
|
""
|
||||||
|
"none"))}}
|
||||||
|
@item]]))
|
||||||
|
|
||||||
|
(defn view []
|
||||||
|
(let [items (observable-collection {:a 1 :b 2})
|
||||||
|
items-view (items-view/items-view :ul item-view
|
||||||
|
items)]
|
||||||
|
[:div
|
||||||
|
items-view
|
||||||
|
[:div
|
||||||
|
[:span "New Item:"]
|
||||||
|
[:button {:on-click (fn [e] (transact! items [:assoc! 0 57]))} "Add"]
|
||||||
|
]
|
||||||
|
]))
|
||||||
|
|
||||||
|
(dom/mount! (.getElementById js/document "root") (view))
|
||||||
|
|
||||||
|
(fw/watch-and-reload)
|
Loading…
Reference in a new issue