From 758dd4f93664c1d4909ac9f37b136b854960d314 Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Thu, 18 Jun 2015 20:59:27 -0700 Subject: [PATCH 01/10] Quick/dirty attempt at supporting custom DOM API. --- project.clj | 2 +- src/freactive/dom.cljs | 46 +++++++++++++++++++++++++----------- src/freactive/ui_common.cljs | 4 ++++ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/project.clj b/project.clj index bcff506..78a3dd1 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject freactive "0.2.0-SNAPSHOT" +(defproject freactive "0.3.0-SNAPSHOT" :description "High-performance, pure Clojurescript, declarative DOM library" :url "https://github.com/aaronc/freactive" :license {:name "Eclipse Public License" diff --git a/src/freactive/dom.cljs b/src/freactive/dom.cljs index 5f44672..ffe531f 100644 --- a/src/freactive/dom.cljs +++ b/src/freactive/dom.cljs @@ -100,6 +100,23 @@ map in velem." (defn register-node-prefix! [prefix xml-ns-or-handler] (aset node-ns-lookup (name prefix) xml-ns-or-handler)) +(def ^:private create-element-lookup + #js {}) + +(defn register-create-element! [tag-name create-api] + (aset create-element-lookup (name tag-name) create-api)) + +(def ^:private default-create-element + (reify ui/ICreateElement + (createElement [this tag] (.createElement js/document tag)) + (createElementNS [this tag ns-uri] (.createElementNS js/document tag ns-uri)))) + +(defn dom-api + [node] + (if-let [api (.-freactive-dom-api node)] + (api node) + node)) + (def ^:private attr-ns-lookup #js {"node" (fn [_ _ _]) @@ -121,19 +138,19 @@ map in velem." ;; (println "insert" (goog/getUid dom-node) ;; "dom-parent" dom-parent (goog/getUid dom-parent) ;; "dom-before" dom-before (goog/getUid dom-before)) - (.insertBefore dom-parent dom-node dom-before)) + (.insertBefore (dom-api dom-parent) dom-node dom-before)) (do ;; (println "append" (goog/getUid dom-node) ;; "dom-parent" dom-parent (goog/getUid dom-parent)) - (.appendChild dom-parent dom-node))))) + (.appendChild (dom-api dom-parent) dom-node))))) (defn- dom-remove [dom-node] - (when-let [parent (.-parentNode dom-node)] - (.removeChild parent dom-node))) + (when-let [parent (.-parentNode (dom-api dom-node))] + (.removeChild (dom-api parent) dom-node))) (defn- dom-simple-replace [new-node old-node] - (when-let [parent (.-parentNode old-node)] - (.replaceChild parent new-node old-node))) + (when-let [parent (.-parentNode (dom-api old-node))] + (.replaceChild (dom-api parent) new-node old-node))) (defn- dom-remove-replace [new-node old-velem] (let [parent (ui/velem-parent old-velem) @@ -158,7 +175,7 @@ map in velem." (dom-insert vparent node vnext-sibling) this) (-velem-take [this] - (dom-remove node)) + (dom-remove node)) (-velem-replace [this old-velem] (if-let [old-node (ui/velem-native-element old-velem)] (dom-simple-replace node old-node) @@ -237,8 +254,8 @@ map in velem." (defn- set-attr! [element attr-name attr-value] (if attr-value - (.setAttribute element attr-name (normalize-attr-value attr-value)) - (.removeAttribute element attr-name))) + (.setAttribute (dom-api element) attr-name (normalize-attr-value attr-value)) + (.removeAttribute (dom-api element) attr-name))) (defn- set-style! [elem prop-name prop-value] ;(println "set-style-prop!" elem prop-name prop-value) @@ -326,9 +343,9 @@ map in velem." (fn [attr-value] ;(println "setting attr" element attr-name attr-value) (if attr-value - (.setAttributeNS element attr-ns attr-name + (.setAttributeNS (dom-api element) attr-ns attr-name (normalize-attr-value attr-value)) - (.removeAttributeNS element attr-ns attr-name)) + (.removeAttributeNS (dom-api element) attr-ns attr-name)) attr-value)) (def ^:private special-attrs @@ -374,9 +391,10 @@ map in velem." (ensureNode [this] (when-not node (set! node - (if ns-uri - (.createElementNS js/document ns-uri tag) - (.createElement js/document tag))) + (let [create-element-api (or (aget create-element-lookup tag) default-create-element)] + (if ns-uri + (ui/createElementNS create-element-api ns-uri tag) + (ui/createElement create-element-api tag)))) (set! (.-freactive-state node) this) (set! attr-binder (bind-attrs! node attrs)) (doseq [child children] diff --git a/src/freactive/ui_common.cljs b/src/freactive/ui_common.cljs index 32b400a..5d7bd14 100644 --- a/src/freactive/ui_common.cljs +++ b/src/freactive/ui_common.cljs @@ -2,6 +2,10 @@ (:require [freactive.core :as r])) +(defprotocol ICreateElement + (createElement [this tag]) + (createElementNS [this tag ns-uri])) + (defprotocol IVirtualElement "Warning: this is currently an internal API subject to change or sudden removal. From 7bf13d9dd1931d257ea7c90e00be0ed1da9604cf Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Sat, 20 Jun 2015 08:10:11 -0700 Subject: [PATCH 02/10] FIrst cut using suggested INativeAPI protocol. --- src/freactive/dom.cljs | 215 ++++++++++++++++++++--------------- src/freactive/ui_common.cljs | 18 ++- 2 files changed, 141 insertions(+), 92 deletions(-) diff --git a/src/freactive/dom.cljs b/src/freactive/dom.cljs index ffe531f..7f07ce9 100644 --- a/src/freactive/dom.cljs +++ b/src/freactive/dom.cljs @@ -1,23 +1,23 @@ (ns freactive.dom (:require - [freactive.core :as r] - [freactive.ui-common :as ui] - [goog.object])) + [freactive.core :as r] + [freactive.ui-common :as ui] + [goog.object])) ;; ## Polyfills (def request-animation-frame (or - (.-requestAnimationFrame js/window) - (.-webkitRequestAnimationFrame js/window) - (.-mozRequestAnimationFrame js/window) - (.-msRequestAnimationFrame js/window) - (.-oRequestAnimationFrame js/window) - (let [t0 (.getTime (js/Date.))] - (fn [f] - (js/setTimeout - #(f (- (.getTime (js/Date.)) t0)) - 16.66666))))) + (.-requestAnimationFrame js/window) + (.-webkitRequestAnimationFrame js/window) + (.-mozRequestAnimationFrame js/window) + (.-msRequestAnimationFrame js/window) + (.-oRequestAnimationFrame js/window) + (let [t0 (.getTime (js/Date.))] + (fn [f] + (js/setTimeout + #(f (- (.getTime (js/Date.)) t0)) + 16.66666))))) ;; Render Loop @@ -42,7 +42,7 @@ (defonce render-loop (request-animation-frame - (fn render[frame-ms] + (fn render [frame-ms] (binding [*animating* true] (reset! frame-time frame-ms) (when enable-fps-instrumentation @@ -95,32 +95,63 @@ map in velem." (def ^:private node-ns-lookup #js - {"svg" "http://www.w3.org/2000/svg"}) + {"svg" "http://www.w3.org/2000/svg"}) (defn register-node-prefix! [prefix xml-ns-or-handler] (aset node-ns-lookup (name prefix) xml-ns-or-handler)) -(def ^:private create-element-lookup +(def ^:private native-api-lookup #js {}) -(defn register-create-element! [tag-name create-api] - (aset create-element-lookup (name tag-name) create-api)) - -(def ^:private default-create-element - (reify ui/ICreateElement - (createElement [this tag] (.createElement js/document tag)) - (createElementNS [this tag ns-uri] (.createElementNS js/document tag ns-uri)))) - -(defn dom-api +(defn register-native-api! [tag api] + (aset native-api-lookup (name tag) api)) + +(def ^:private default-native-api + (reify ui/INativeAPI + (native-queue [this f]) + (native-create-element [this elem-ns elem-name] + (let [elem (if (some? elem-ns) + (.createElementNS js/document elem-name elem-ns) + (.createElement js/document elem-name))] + (set! (.-freactive-native-api elem) default-native-api) + elem)) + (native-create-text-node [this text] + (.createTextNode text)) + (native-get-attr [this elem attr-name] + (.getAttribute elem attr-name)) + (native-set-attr! [this elem attr-name attr-val] + (.setAttribute elem attr-name attr-val)) + (native-remove-attr! [this elem attr-name] + (.removeAttribute elem attr-name)) + (native-insert [this parent elem before?] + (set! (.-freactive-parent elem) (fn [] (ui/native-parent-node this elem))) + (if before? + (.insertBefore parent elem before?) + (.appendChild parent elem))) + (native-replace [this elem new-elem old-elem] + (set! (.-freactive-parent new-elem) (fn [] (ui/native-parent-node this new-elem))) + (.replaceChild elem new-elem old-elem)) + (native-remove [this elem child-elem] + (.removeChild elem child-elem)) + (native-element? [this x] + (instance? js/Node x)) + (native-text-node? [this x] + (instance? js/Text x)) + (native-set-text-node! [this node text] + (set! (.-textContent node) text)) + (native-parent-node [this node] + (.-parentNode node)) + (native-last-child [this node] + (.-lastChild node)))) + +(defn- get-native-api [node] - (if-let [api (.-freactive-dom-api node)] - (api node) - node)) + (or (.-freactive-native-api node) default-native-api)) (def ^:private attr-ns-lookup #js - {"node" (fn [_ _ _]) - "state" (fn [_ _ _])}) + {"node" (fn [_ _ _]) + "state" (fn [_ _ _])}) (defn register-attr-prefix! [prefix xml-ns-or-handler] (aset attr-ns-lookup (name prefix) xml-ns-or-handler)) @@ -131,26 +162,31 @@ map in velem." (.-freactive-state x)) (defn- dom-insert [parent dom-node vnext-sibling] - (let [dom-parent (ui/native-parent parent)] + (let [dom-parent (ui/native-parent parent) + api (get-native-api dom-parent)] ;; (when vnext-sibling (println "vnext" (type vnext-sibling))) - (if-let [dom-before (ui/next-native-sibling vnext-sibling)] + (if-let [dom-before (ui/next-native-sibling vnext-sibling)] (do ;; (println "insert" (goog/getUid dom-node) ;; "dom-parent" dom-parent (goog/getUid dom-parent) ;; "dom-before" dom-before (goog/getUid dom-before)) - (.insertBefore (dom-api dom-parent) dom-node dom-before)) + (ui/native-insert api dom-parent dom-node dom-before) + #_(.insertBefore (dom-api dom-parent) dom-node dom-before)) (do ;; (println "append" (goog/getUid dom-node) ;; "dom-parent" dom-parent (goog/getUid dom-parent)) - (.appendChild (dom-api dom-parent) dom-node))))) + (ui/native-insert api dom-parent dom-node false) + #_(.appendChild (dom-api dom-parent) dom-node))))) (defn- dom-remove [dom-node] - (when-let [parent (.-parentNode (dom-api dom-node))] - (.removeChild (dom-api parent) dom-node))) + (when-let [parent (ui/native-parent-node (get-native-api dom-node) dom-node) #_(.-parentNode (dom-api old-node))] + (ui/native-remove (get-native-api parent) parent dom-node) + #_(.removeChild (dom-api parent) dom-node))) (defn- dom-simple-replace [new-node old-node] - (when-let [parent (.-parentNode (dom-api old-node))] - (.replaceChild (dom-api parent) new-node old-node))) + (when-let [parent (ui/native-parent-node (get-native-api old-node) old-node) #_(.-parentNode (dom-api old-node))] + (ui/native-replace (get-native-api parent) parent new-node old-node) + #_(.replaceChild (dom-api parent) new-node old-node))) (defn- dom-remove-replace [new-node old-velem] (let [parent (ui/velem-parent old-velem) @@ -218,18 +254,18 @@ map in velem." (when clean-fn (clean-fn)) (when states (goog.object/forEach - states - (fn [state k _] - (when state - (when (.-clean state) - (.clean state))))))) + states + (fn [state k _] + (when state + (when (.-clean state) + (.clean state))))))) (dispose [this] (when states (goog.object/forEach - states - (fn [state k _] - (when state - (r/dispose state))))))) + states + (fn [state k _] + (when state + (r/dispose state))))))) (defn- wrap-attr-map-binder ([bind-fn] @@ -254,8 +290,8 @@ map in velem." (defn- set-attr! [element attr-name attr-value] (if attr-value - (.setAttribute (dom-api element) attr-name (normalize-attr-value attr-value)) - (.removeAttribute (dom-api element) attr-name))) + (ui/native-set-attr! (get-native-api element) element attr-name attr-value) + (ui/native-remove-attr! (get-native-api element) element attr-name))) (defn- set-style! [elem prop-name prop-value] ;(println "set-style-prop!" elem prop-name prop-value) @@ -272,7 +308,7 @@ map in velem." (defn ^:dynamic ^:pluggable unlisten! "Removes an event handler. Can be replaced by a plugin such as goog.events." [element evt-name handler] - (.removeEventListener element evt-name handler)) + (.removeEventListener element evt-name handler)) (deftype EventBinding [node event-name ^:mutable handler] IFn @@ -304,7 +340,8 @@ map in velem." (set-attr! element "data-state" state)) (defn- get-data-state [element] - (.getAttribute element "data-state")) + (ui/native-get-attr (get-native-api element) element "data-state") + #_(.getAttribute element "data-state")) (defn- get-state-attr [state attr-str] (when-let [attrs (when state (.-attrs state))] @@ -312,22 +349,22 @@ map in velem." (defn- set-data-state! ([element state] - (let [cur-state (get-data-state element) - node-state (get-element-state element) - state (when state (name state))] - (when-not (identical? cur-state state) - (do-set-data-state! element state) - (when-let [enter-transition (get-state-attr node-state (str ":state/on-" state))] - (enter-transition element cur-state state)))))) + (let [cur-state (get-data-state element) + node-state (get-element-state element) + state (when state (name state))] + (when-not (identical? cur-state state) + (do-set-data-state! element state) + (when-let [enter-transition (get-state-attr node-state (str ":state/on-" state))] + (enter-transition element cur-state state)))))) (def ^:private attr-setters #js - {:data-state (fn [element state] - (set-data-state! element state) - state) - :class (fn [element cls] - (set! (.-className element) (if (nil? cls) "" cls)) - cls)}) + {:data-state (fn [element state] + (set-data-state! element state) + state) + :class (fn [element cls] + (set! (.-className element) (if (nil? cls) "" cls)) + cls)}) ;; attributes to set directly (doseq [a #js ["id" "value"]] @@ -339,18 +376,19 @@ map in velem." (fn [attr-value] (set-attr! element attr-name attr-value)))) +;;; TODO - do we need this? (defn- get-ns-attr-setter [element attr-ns attr-name] (fn [attr-value] - ;(println "setting attr" element attr-name attr-value) - (if attr-value - (.setAttributeNS (dom-api element) attr-ns attr-name - (normalize-attr-value attr-value)) - (.removeAttributeNS (dom-api element) attr-ns attr-name)) - attr-value)) + ;(println "setting attr" element attr-name attr-value) + (if attr-value + (.setAttributeNS (dom-api element) attr-ns attr-name + (normalize-attr-value attr-value)) + (.removeAttributeNS (dom-api element) attr-ns attr-name)) + attr-value)) (def ^:private special-attrs #js {"events" (wrap-attr-map-binder bind-event!) - "style" (wrap-attr-map-binder bind-style!)}) + "style" (wrap-attr-map-binder bind-style!)}) (defn- bind-attr! [element attr-key attr-value] (let [attr-ns (namespace attr-key) @@ -378,6 +416,7 @@ map in velem." (def ^:private bind-attrs! (wrap-attr-map-binder bind-attr!)) +;;; TODO - pass in native API here? (deftype DOMElement [ns-uri tag ^:mutable attrs children ^:mutable node ^:mutable parent ^:mutable attr-binder] IHash @@ -391,10 +430,8 @@ map in velem." (ensureNode [this] (when-not node (set! node - (let [create-element-api (or (aget create-element-lookup tag) default-create-element)] - (if ns-uri - (ui/createElementNS create-element-api ns-uri tag) - (ui/createElement create-element-api tag)))) + (let [native-api (or (aget native-api-lookup tag) default-native-api)] + (ui/native-create-element native-api ns-uri tag))) (set! (.-freactive-state node) this) (set! attr-binder (bind-attrs! node attrs)) (doseq [child children] @@ -420,7 +457,7 @@ map in velem." (.onAttached this) this) (-velem-take [this] - (dom-remove node)) + (dom-remove node)) (-velem-replace [this old-velem] (.ensureNode this) (if-let [old-node (ui/velem-native-element old-velem)] @@ -455,7 +492,7 @@ map in velem." (dom-insert parent node vnext-sibling) this) (-velem-take [this] - (dom-remove node)) + (dom-remove node)) (-velem-replace [this old-velem] (if-let [old-node (ui/velem-native-element old-velem)] (do @@ -481,7 +518,7 @@ map in velem." Can be used to define custom conversions to DOM nodes or text for things such as numbers or dates; or can be used to define containers for DOM elements themselves." (-get-dom-image [x] - "Should return either virtual DOM (a vector or string) or an actual DOM node.")) + "Should return either virtual DOM (a vector or string) or an actual DOM node.")) (extend-protocol IDOMImage nil @@ -494,9 +531,9 @@ or dates; or can be used to define containers for DOM elements themselves." (-get-dom-image [x] (str x))) ;; From hiccup.compiler: -(def ^{:doc "Regular expression that parses a CSS-style id and class from an element name." +(def ^{:doc "Regular expression that parses a CSS-style id and class from an element name." :private true} - re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?") +re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?") (def ^:private re-dot (js/RegExp. "\\." "g")) @@ -522,14 +559,14 @@ or dates; or can be used to define containers for DOM elements themselves." attrs (if have-attrs attrs? {}) attrs (cond-> attrs - (and id (not (:id attrs))) - (assoc :id id) - - class - (update :class - (fn [cls] - (let [class (.replace class re-dot " ")] - (if cls (str class " " cls) class))))) + (and id (not (:id attrs))) + (assoc :id id) + + class + (update :class + (fn [cls] + (let [class (.replace class re-dot " ")] + (if cls (str class " " cls) class))))) children (if have-attrs (rest tail) tail) children* (append-children* #js [] children)] @@ -679,7 +716,7 @@ document body." (recur)))) (let [vroot (wrap-unmanaged-node root-node nil)] (configure-root! vroot vdom)))) - root-node)) + root-node)) (defn unmount! [mount-point] (let [root-node diff --git a/src/freactive/ui_common.cljs b/src/freactive/ui_common.cljs index 5d7bd14..cd7b15d 100644 --- a/src/freactive/ui_common.cljs +++ b/src/freactive/ui_common.cljs @@ -2,9 +2,21 @@ (:require [freactive.core :as r])) -(defprotocol ICreateElement - (createElement [this tag]) - (createElementNS [this tag ns-uri])) +(defprotocol INativeAPI + (native-queue [this f] "Queues the no-arg fn f to be run in the application thread of this UI platform") + (native-create-element [this elem-ns elem-name]) + (native-create-text-node [this text]) + (native-get-attr [this elem attr-name]) + (native-set-attr! [this elem attr-name attr-val]) + (native-remove-attr! [this elem attr-name]) + (native-insert [this parent elem before?]) + (native-replace [this elem new-elem old-elem]) + (native-remove [this elem child-elem]) + (native-element? [this x]) + (native-text-node? [this x]) + (native-set-text-node! [this node text]) + (native-parent-node [this node]) + (native-last-child [this node])) (defprotocol IVirtualElement "Warning: this is currently an internal API subject to change or sudden removal. From 07334c44ac4edfc2579d247e26ab65fb4936c8c9 Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Sat, 20 Jun 2015 13:03:06 -0700 Subject: [PATCH 03/10] get/set functions for native api and parent node fn. --- src/freactive/dom.cljs | 14 +++++++++----- src/freactive/ui_common.cljs | 8 ++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/freactive/dom.cljs b/src/freactive/dom.cljs index 7f07ce9..e4864cd 100644 --- a/src/freactive/dom.cljs +++ b/src/freactive/dom.cljs @@ -113,7 +113,7 @@ map in velem." (let [elem (if (some? elem-ns) (.createElementNS js/document elem-name elem-ns) (.createElement js/document elem-name))] - (set! (.-freactive-native-api elem) default-native-api) + (ui/set-native-api elem default-native-api) elem)) (native-create-text-node [this text] (.createTextNode text)) @@ -124,12 +124,12 @@ map in velem." (native-remove-attr! [this elem attr-name] (.removeAttribute elem attr-name)) (native-insert [this parent elem before?] - (set! (.-freactive-parent elem) (fn [] (ui/native-parent-node this elem))) + (ui/set-parent-node-fn default-native-api elem) (if before? (.insertBefore parent elem before?) (.appendChild parent elem))) (native-replace [this elem new-elem old-elem] - (set! (.-freactive-parent new-elem) (fn [] (ui/native-parent-node this new-elem))) + (ui/set-parent-node-fn default-native-api elem) (.replaceChild elem new-elem old-elem)) (native-remove [this elem child-elem] (.removeChild elem child-elem)) @@ -148,6 +148,10 @@ map in velem." [node] (or (.-freactive-native-api node) default-native-api)) +(defn- get-native-parent-fn + [node] + (or (.-freactive-parent node) (fn [] (ui/native-parent-node default-native-api node)))) + (def ^:private attr-ns-lookup #js {"node" (fn [_ _ _]) @@ -179,12 +183,12 @@ map in velem." #_(.appendChild (dom-api dom-parent) dom-node))))) (defn- dom-remove [dom-node] - (when-let [parent (ui/native-parent-node (get-native-api dom-node) dom-node) #_(.-parentNode (dom-api old-node))] + (when-let [parent ((get-native-parent-fn dom-node)) #_(.-parentNode (dom-api old-node))] (ui/native-remove (get-native-api parent) parent dom-node) #_(.removeChild (dom-api parent) dom-node))) (defn- dom-simple-replace [new-node old-node] - (when-let [parent (ui/native-parent-node (get-native-api old-node) old-node) #_(.-parentNode (dom-api old-node))] + (when-let [parent ((get-native-parent-fn old-node)) #_(.-parentNode (dom-api old-node))] (ui/native-replace (get-native-api parent) parent new-node old-node) #_(.replaceChild (dom-api parent) new-node old-node))) diff --git a/src/freactive/ui_common.cljs b/src/freactive/ui_common.cljs index cd7b15d..e785179 100644 --- a/src/freactive/ui_common.cljs +++ b/src/freactive/ui_common.cljs @@ -18,6 +18,14 @@ (native-parent-node [this node]) (native-last-child [this node])) +(defn set-native-api + [elem native-api] + (set! (.-freactive-native-api elem) native-api)) + +(defn set-parent-node-fn + [api elem] + (set! (.-freactive-parent elem) (fn [] (native-parent-node api elem)))) + (defprotocol IVirtualElement "Warning: this is currently an internal API subject to change or sudden removal. From a8db872953cdfacb263608c9a878a60d1acd10a3 Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Sat, 20 Jun 2015 14:22:06 -0700 Subject: [PATCH 04/10] Wrong signature on .createElementNS --- src/freactive/dom.cljs | 2 +- src/freactive/ui_common.cljs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/freactive/dom.cljs b/src/freactive/dom.cljs index e4864cd..13a29d6 100644 --- a/src/freactive/dom.cljs +++ b/src/freactive/dom.cljs @@ -111,7 +111,7 @@ map in velem." (native-queue [this f]) (native-create-element [this elem-ns elem-name] (let [elem (if (some? elem-ns) - (.createElementNS js/document elem-name elem-ns) + (.createElementNS js/document elem-ns elem-name) (.createElement js/document elem-name))] (ui/set-native-api elem default-native-api) elem)) diff --git a/src/freactive/ui_common.cljs b/src/freactive/ui_common.cljs index e785179..5b3001c 100644 --- a/src/freactive/ui_common.cljs +++ b/src/freactive/ui_common.cljs @@ -23,8 +23,10 @@ (set! (.-freactive-native-api elem) native-api)) (defn set-parent-node-fn - [api elem] - (set! (.-freactive-parent elem) (fn [] (native-parent-node api elem)))) + ([api elem] + (set-parent-node-fn api elem (fn [] (native-parent-node api elem)))) + ([api elem parent-node-fn] + (set! (.-freactive-parent elem) parent-node-fn))) (defprotocol IVirtualElement "Warning: this is currently an internal API subject to change or sudden removal. From 920dc76f0042463d72156c5ab41fc962d801c6da Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Sun, 21 Jun 2015 07:56:38 -0700 Subject: [PATCH 05/10] Refactor get/set of native API to freactive.dom. --- src/freactive/dom.cljs | 25 +++++++++++++++++++------ src/freactive/ui_common.cljs | 10 ---------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/freactive/dom.cljs b/src/freactive/dom.cljs index 13a29d6..4df74b8 100644 --- a/src/freactive/dom.cljs +++ b/src/freactive/dom.cljs @@ -113,7 +113,6 @@ map in velem." (let [elem (if (some? elem-ns) (.createElementNS js/document elem-ns elem-name) (.createElement js/document elem-name))] - (ui/set-native-api elem default-native-api) elem)) (native-create-text-node [this text] (.createTextNode text)) @@ -124,12 +123,10 @@ map in velem." (native-remove-attr! [this elem attr-name] (.removeAttribute elem attr-name)) (native-insert [this parent elem before?] - (ui/set-parent-node-fn default-native-api elem) (if before? (.insertBefore parent elem before?) (.appendChild parent elem))) (native-replace [this elem new-elem old-elem] - (ui/set-parent-node-fn default-native-api elem) (.replaceChild elem new-elem old-elem)) (native-remove [this elem child-elem] (.removeChild elem child-elem)) @@ -148,10 +145,20 @@ map in velem." [node] (or (.-freactive-native-api node) default-native-api)) +(defn- set-native-api! + [elem native-api] + (set! (.-freactive-native-api elem) native-api)) + (defn- get-native-parent-fn [node] (or (.-freactive-parent node) (fn [] (ui/native-parent-node default-native-api node)))) +(defn- set-native-parent-fn! + ([api elem] + (set-native-parent-fn! api elem (fn [] (ui/native-parent-node api elem)))) + ([api elem parent-node-fn] + (set! (.-freactive-parent elem) parent-node-fn))) + (def ^:private attr-ns-lookup #js {"node" (fn [_ _ _]) @@ -174,11 +181,13 @@ map in velem." ;; (println "insert" (goog/getUid dom-node) ;; "dom-parent" dom-parent (goog/getUid dom-parent) ;; "dom-before" dom-before (goog/getUid dom-before)) + (set-native-parent-fn! api dom-node) (ui/native-insert api dom-parent dom-node dom-before) #_(.insertBefore (dom-api dom-parent) dom-node dom-before)) (do ;; (println "append" (goog/getUid dom-node) ;; "dom-parent" dom-parent (goog/getUid dom-parent)) + (set-native-parent-fn! api dom-node) (ui/native-insert api dom-parent dom-node false) #_(.appendChild (dom-api dom-parent) dom-node))))) @@ -189,7 +198,9 @@ map in velem." (defn- dom-simple-replace [new-node old-node] (when-let [parent ((get-native-parent-fn old-node)) #_(.-parentNode (dom-api old-node))] - (ui/native-replace (get-native-api parent) parent new-node old-node) + (let [api (get-native-api parent)] + (set-native-parent-fn! api new-node) + (ui/native-replace api parent new-node old-node)) #_(.replaceChild (dom-api parent) new-node old-node))) (defn- dom-remove-replace [new-node old-velem] @@ -434,8 +445,10 @@ map in velem." (ensureNode [this] (when-not node (set! node - (let [native-api (or (aget native-api-lookup tag) default-native-api)] - (ui/native-create-element native-api ns-uri tag))) + (let [native-api (or (aget native-api-lookup tag) default-native-api) + elem (ui/native-create-element native-api ns-uri tag)] + (set-native-api! elem native-api) + elem)) (set! (.-freactive-state node) this) (set! attr-binder (bind-attrs! node attrs)) (doseq [child children] diff --git a/src/freactive/ui_common.cljs b/src/freactive/ui_common.cljs index 5b3001c..cd7b15d 100644 --- a/src/freactive/ui_common.cljs +++ b/src/freactive/ui_common.cljs @@ -18,16 +18,6 @@ (native-parent-node [this node]) (native-last-child [this node])) -(defn set-native-api - [elem native-api] - (set! (.-freactive-native-api elem) native-api)) - -(defn set-parent-node-fn - ([api elem] - (set-parent-node-fn api elem (fn [] (native-parent-node api elem)))) - ([api elem parent-node-fn] - (set! (.-freactive-parent elem) parent-node-fn))) - (defprotocol IVirtualElement "Warning: this is currently an internal API subject to change or sudden removal. From 9cbf46b64f9dcda890fecd09a577859e3b1b8a36 Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Sun, 21 Jun 2015 10:51:02 -0700 Subject: [PATCH 06/10] Attribute namespace --- src/freactive/dom.cljs | 31 +++++++++++++++++++------------ src/freactive/ui_common.cljs | 6 +++--- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/freactive/dom.cljs b/src/freactive/dom.cljs index 4df74b8..db723e6 100644 --- a/src/freactive/dom.cljs +++ b/src/freactive/dom.cljs @@ -116,12 +116,18 @@ map in velem." elem)) (native-create-text-node [this text] (.createTextNode text)) - (native-get-attr [this elem attr-name] - (.getAttribute elem attr-name)) - (native-set-attr! [this elem attr-name attr-val] - (.setAttribute elem attr-name attr-val)) - (native-remove-attr! [this elem attr-name] - (.removeAttribute elem attr-name)) + (native-get-attr [this elem attr-ns attr-name] + (if attr-ns + (.getAttributeNS elem attr-ns attr-name) + (.getAttribute elem attr-name))) + (native-set-attr! [this elem attr-ns attr-name attr-val] + (if attr-ns + (.setAttributeNS elem attr-ns attr-name attr-val) + (.setAttribute elem attr-name attr-val))) + (native-remove-attr! [this elem attr-ns attr-name] + (if attr-ns + (.removeAttributeNS elem attr-ns attr-name) + (.removeAttribute elem attr-name))) (native-insert [this parent elem before?] (if before? (.insertBefore parent elem before?) @@ -305,8 +311,8 @@ map in velem." (defn- set-attr! [element attr-name attr-value] (if attr-value - (ui/native-set-attr! (get-native-api element) element attr-name attr-value) - (ui/native-remove-attr! (get-native-api element) element attr-name))) + (ui/native-set-attr! (get-native-api element) element nil attr-name attr-value) + (ui/native-remove-attr! (get-native-api element) element nil attr-name))) (defn- set-style! [elem prop-name prop-value] ;(println "set-style-prop!" elem prop-name prop-value) @@ -355,7 +361,7 @@ map in velem." (set-attr! element "data-state" state)) (defn- get-data-state [element] - (ui/native-get-attr (get-native-api element) element "data-state") + (ui/native-get-attr (get-native-api element) element nil "data-state") #_(.getAttribute element "data-state")) (defn- get-state-attr [state attr-str] @@ -391,14 +397,15 @@ map in velem." (fn [attr-value] (set-attr! element attr-name attr-value)))) -;;; TODO - do we need this? (defn- get-ns-attr-setter [element attr-ns attr-name] (fn [attr-value] ;(println "setting attr" element attr-name attr-value) (if attr-value - (.setAttributeNS (dom-api element) attr-ns attr-name + (ui/native-set-attr! (get-native-api element) element attr-ns attr-name attr-value) + (ui/native-remove-attr! (get-native-api element) element attr-ns attr-name) + #_(.setAttributeNS (dom-api element) attr-ns attr-name (normalize-attr-value attr-value)) - (.removeAttributeNS (dom-api element) attr-ns attr-name)) + #_(.removeAttributeNS (dom-api element) attr-ns attr-name)) attr-value)) (def ^:private special-attrs diff --git a/src/freactive/ui_common.cljs b/src/freactive/ui_common.cljs index cd7b15d..29f6fc6 100644 --- a/src/freactive/ui_common.cljs +++ b/src/freactive/ui_common.cljs @@ -6,9 +6,9 @@ (native-queue [this f] "Queues the no-arg fn f to be run in the application thread of this UI platform") (native-create-element [this elem-ns elem-name]) (native-create-text-node [this text]) - (native-get-attr [this elem attr-name]) - (native-set-attr! [this elem attr-name attr-val]) - (native-remove-attr! [this elem attr-name]) + (native-get-attr [this elem attr-ns attr-name]) + (native-set-attr! [this elem attr-ns attr-name attr-val]) + (native-remove-attr! [this elem attr-ns attr-name]) (native-insert [this parent elem before?]) (native-replace [this elem new-elem old-elem]) (native-remove [this elem child-elem]) From 6a5167955a496394f1038ba7c60d829dfcf77ebb Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Thu, 9 Jul 2015 11:31:15 -0700 Subject: [PATCH 07/10] Match project version in aaronc/freactive --- project.clj | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/project.clj b/project.clj index 78a3dd1..914e670 100644 --- a/project.clj +++ b/project.clj @@ -1,36 +1,11 @@ -(defproject freactive "0.3.0-SNAPSHOT" +(defproject allgress/freactive "0.2.0-SNAPSHOT" :description "High-performance, pure Clojurescript, declarative DOM library" :url "https://github.com/aaronc/freactive" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/data.avl "0.0.12"] + :dependencies [[org.clojure/clojure "1.7.0-RC2"] + [org.clojure/clojurescript "0.0-3308"] [garden "1.2.5"] - [freactive.core "0.2.0-SNAPSHOT"]] - :profiles - {:dev - {:plugins [[lein-cljsbuild "1.0.5"] - [lein-figwheel "0.3.3" :exclusions [org.cloure/clojure]]] - :dependencies - [[org.clojure/clojure "1.7.0-RC1"] - [org.clojure/clojurescript "0.0-3269"] - [figwheel "0.3.3" :exclusions [org.cloure/clojure]] - [org.clojure/core.async "0.1.346.0-17112a-alpha"] - [bardo "0.1.0" :exclusions [org.clojure/clojure]]] - :cljsbuild {:builds - [{:id "example" - :source-paths ["src" "example" - "checkouts/freactive.core/src/clojure" - "checkouts/freactive.core/test"] - :compiler {:output-to "resources/public/js/compiled/app.js" - :output-dir "resources/public/js/compiled/out" - :optimizations :none - :pretty-print true - :source-map true}} - {:id "example-advanced" - :source-paths ["src" "example" "test" "checkouts/freactive.core/src/clojure"] - :compiler {:output-to "resources/public/js/compiled/advanced.js" - :output-dir "resources/public/js/compiled/out-adv" - :optimizations :advanced - :main "freactive.dom-perf"}}]}}} - :source-paths ["src"] - :test-paths ["test" "example"]) + [freactive.core "0.2.0-SNAPSHOT"] + [org.clojure/core.async "0.1.346.0-17112a-alpha"] + [bardo "0.1.0" :exclusions [org.clojure/clojure]]]) From 5ceb8e88f03482dff8876a01af31a7de2ab6d9db Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Thu, 9 Jul 2015 11:35:01 -0700 Subject: [PATCH 08/10] Match project.clj in aaronc/freactive --- build.boot | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ project.clj | 37 +++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 build.boot diff --git a/build.boot b/build.boot new file mode 100644 index 0000000..72d9072 --- /dev/null +++ b/build.boot @@ -0,0 +1,59 @@ +(set-env! + :source-paths #{"src" "test"} + :resource-paths #{"src"} + :wagons '[[s3-wagon-private "1.1.2"]] + :repositories [["clojars" "http://clojars.org/repo/"] + ["maven-central" "http://repo1.maven.org/maven2/"] + ["my.datomic.com" {:url "https://my.datomic.com/repo" + :username (System/getenv "DATOMIC_USERNAME") + :password (System/getenv "DATOMIC_PASSWORD")}] + ["releases" {:url "http://archiva:8080/repository/internal" + :username (System/getenv "ARCHIVA_USERNAME") + :password (System/getenv "ARCHIVA_PASSWORD")}]] + + :dependencies '[[adzerk/boot-cljs "0.0-3308-0" :scope "test"] + [adzerk/boot-cljs-repl "0.1.9" :scope "test"] + [adzerk/boot-reload "0.3.1" :scope "test"] + [pandeiro/boot-http "0.6.2" :scope "test"] + [cljsjs/boot-cljsjs "0.5.0" :scope "test"] + [allgress/boot-tasks "0.2.2" :scope "test"]]) + +(require + '[adzerk.boot-cljs :refer :all] + '[adzerk.boot-cljs-repl :refer :all] + '[adzerk.boot-reload :refer :all] + '[allgress.boot-tasks :refer :all] + '[pandeiro.boot-http :refer :all] + '[cljsjs.boot-cljsjs :refer :all]) + +(set-project-deps!) + +(default-task-options!) + +(task-options! + reload {:on-jsload 'allgress.cereus.core/on-jsload}) + +(deftask web-dev + "Developer workflow for web-component UX." + [] + (comp + (asset-paths :asset-paths #{"html" "bower_components"}) + (from-cljsjs) + (serve :dir "target/") + #_(run-jar :jarfile "../web/target/web_0.7.0_standalone.jar -e pluto -a admin -p 8081") + ;;(run-jar :jarfile "../login/target/login-0.1.2.jar") + ;;(run-jar :jarfile "../account-manager/target/account-manager-0.1.5.jar") + (watch) + (speak) + (cljs) + (reload))) + + + + + + +(comment + (run-jar :jarfile "../web/target/web-0.3.0.jar -e dev") + (run-jar :jarfile "../login/target/login-0.1.2.jar -e dev") + (run-jar :jarfile "../account-manager/target/account-manager-0.1.5.jar -e dev")) \ No newline at end of file diff --git a/project.clj b/project.clj index 914e670..3702083 100644 --- a/project.clj +++ b/project.clj @@ -1,11 +1,36 @@ -(defproject allgress/freactive "0.2.0-SNAPSHOT" +(defproject freactive "0.2.0-SNAPSHOT" :description "High-performance, pure Clojurescript, declarative DOM library" :url "https://github.com/aaronc/freactive" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.7.0-RC2"] - [org.clojure/clojurescript "0.0-3308"] + :dependencies [[org.clojure/data.avl "0.0.12"] [garden "1.2.5"] - [freactive.core "0.2.0-SNAPSHOT"] - [org.clojure/core.async "0.1.346.0-17112a-alpha"] - [bardo "0.1.0" :exclusions [org.clojure/clojure]]]) + [freactive.core "0.2.0-SNAPSHOT"]] + :profiles + {:dev + {:plugins [[lein-cljsbuild "1.0.5"] + [lein-figwheel "0.3.3" :exclusions [org.cloure/clojure]]] + :dependencies + [[org.clojure/clojure "1.7.0-RC1"] + [org.clojure/clojurescript "0.0-3269"] + [figwheel "0.3.3" :exclusions [org.cloure/clojure]] + [org.clojure/core.async "0.1.346.0-17112a-alpha"] + [bardo "0.1.0" :exclusions [org.clojure/clojure]]] + :cljsbuild {:builds + [{:id "example" + :source-paths ["src" "example" + "checkouts/freactive.core/src/clojure" + "checkouts/freactive.core/test"] + :compiler {:output-to "resources/public/js/compiled/app.js" + :output-dir "resources/public/js/compiled/out" + :optimizations :none + :pretty-print true + :source-map true}} + {:id "example-advanced" + :source-paths ["src" "example" "test" "checkouts/freactive.core/src/clojure"] + :compiler {:output-to "resources/public/js/compiled/advanced.js" + :output-dir "resources/public/js/compiled/out-adv" + :optimizations :advanced + :main "freactive.dom-perf"}}]}}} + :source-paths ["src"] + :test-paths ["test" "example"]) From 6695cac261181aad3390d52a6cb04ed4c1abe7e1 Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Thu, 9 Jul 2015 11:37:18 -0700 Subject: [PATCH 09/10] Undo project file mess. --- project.clj | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/project.clj b/project.clj index 3702083..fef20c8 100644 --- a/project.clj +++ b/project.clj @@ -1,36 +1,11 @@ -(defproject freactive "0.2.0-SNAPSHOT" +(defproject allgress/freactive "0.3.0" :description "High-performance, pure Clojurescript, declarative DOM library" :url "https://github.com/aaronc/freactive" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/data.avl "0.0.12"] + :dependencies [[org.clojure/clojure "1.7.0-RC2"] + [org.clojure/clojurescript "0.0-3308"] [garden "1.2.5"] - [freactive.core "0.2.0-SNAPSHOT"]] - :profiles - {:dev - {:plugins [[lein-cljsbuild "1.0.5"] - [lein-figwheel "0.3.3" :exclusions [org.cloure/clojure]]] - :dependencies - [[org.clojure/clojure "1.7.0-RC1"] - [org.clojure/clojurescript "0.0-3269"] - [figwheel "0.3.3" :exclusions [org.cloure/clojure]] - [org.clojure/core.async "0.1.346.0-17112a-alpha"] - [bardo "0.1.0" :exclusions [org.clojure/clojure]]] - :cljsbuild {:builds - [{:id "example" - :source-paths ["src" "example" - "checkouts/freactive.core/src/clojure" - "checkouts/freactive.core/test"] - :compiler {:output-to "resources/public/js/compiled/app.js" - :output-dir "resources/public/js/compiled/out" - :optimizations :none - :pretty-print true - :source-map true}} - {:id "example-advanced" - :source-paths ["src" "example" "test" "checkouts/freactive.core/src/clojure"] - :compiler {:output-to "resources/public/js/compiled/advanced.js" - :output-dir "resources/public/js/compiled/out-adv" - :optimizations :advanced - :main "freactive.dom-perf"}}]}}} - :source-paths ["src"] - :test-paths ["test" "example"]) + [freactive.core "0.2.0-SNAPSHOT"] + [org.clojure/core.async "0.1.346.0-17112a-alpha"] + [bardo "0.1.0" :exclusions [org.clojure/clojure]]]) From 029ee2c2f91f19bb5920ec7ea58f14c89fa390e1 Mon Sep 17 00:00:00 2001 From: Dave Dixon Date: Thu, 9 Jul 2015 11:39:25 -0700 Subject: [PATCH 10/10] Match project.clj in aaronc/freactive --- build.boot | 59 ----------------------------------------------------- project.clj | 37 +++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 65 deletions(-) delete mode 100644 build.boot diff --git a/build.boot b/build.boot deleted file mode 100644 index 72d9072..0000000 --- a/build.boot +++ /dev/null @@ -1,59 +0,0 @@ -(set-env! - :source-paths #{"src" "test"} - :resource-paths #{"src"} - :wagons '[[s3-wagon-private "1.1.2"]] - :repositories [["clojars" "http://clojars.org/repo/"] - ["maven-central" "http://repo1.maven.org/maven2/"] - ["my.datomic.com" {:url "https://my.datomic.com/repo" - :username (System/getenv "DATOMIC_USERNAME") - :password (System/getenv "DATOMIC_PASSWORD")}] - ["releases" {:url "http://archiva:8080/repository/internal" - :username (System/getenv "ARCHIVA_USERNAME") - :password (System/getenv "ARCHIVA_PASSWORD")}]] - - :dependencies '[[adzerk/boot-cljs "0.0-3308-0" :scope "test"] - [adzerk/boot-cljs-repl "0.1.9" :scope "test"] - [adzerk/boot-reload "0.3.1" :scope "test"] - [pandeiro/boot-http "0.6.2" :scope "test"] - [cljsjs/boot-cljsjs "0.5.0" :scope "test"] - [allgress/boot-tasks "0.2.2" :scope "test"]]) - -(require - '[adzerk.boot-cljs :refer :all] - '[adzerk.boot-cljs-repl :refer :all] - '[adzerk.boot-reload :refer :all] - '[allgress.boot-tasks :refer :all] - '[pandeiro.boot-http :refer :all] - '[cljsjs.boot-cljsjs :refer :all]) - -(set-project-deps!) - -(default-task-options!) - -(task-options! - reload {:on-jsload 'allgress.cereus.core/on-jsload}) - -(deftask web-dev - "Developer workflow for web-component UX." - [] - (comp - (asset-paths :asset-paths #{"html" "bower_components"}) - (from-cljsjs) - (serve :dir "target/") - #_(run-jar :jarfile "../web/target/web_0.7.0_standalone.jar -e pluto -a admin -p 8081") - ;;(run-jar :jarfile "../login/target/login-0.1.2.jar") - ;;(run-jar :jarfile "../account-manager/target/account-manager-0.1.5.jar") - (watch) - (speak) - (cljs) - (reload))) - - - - - - -(comment - (run-jar :jarfile "../web/target/web-0.3.0.jar -e dev") - (run-jar :jarfile "../login/target/login-0.1.2.jar -e dev") - (run-jar :jarfile "../account-manager/target/account-manager-0.1.5.jar -e dev")) \ No newline at end of file diff --git a/project.clj b/project.clj index fef20c8..3702083 100644 --- a/project.clj +++ b/project.clj @@ -1,11 +1,36 @@ -(defproject allgress/freactive "0.3.0" +(defproject freactive "0.2.0-SNAPSHOT" :description "High-performance, pure Clojurescript, declarative DOM library" :url "https://github.com/aaronc/freactive" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.7.0-RC2"] - [org.clojure/clojurescript "0.0-3308"] + :dependencies [[org.clojure/data.avl "0.0.12"] [garden "1.2.5"] - [freactive.core "0.2.0-SNAPSHOT"] - [org.clojure/core.async "0.1.346.0-17112a-alpha"] - [bardo "0.1.0" :exclusions [org.clojure/clojure]]]) + [freactive.core "0.2.0-SNAPSHOT"]] + :profiles + {:dev + {:plugins [[lein-cljsbuild "1.0.5"] + [lein-figwheel "0.3.3" :exclusions [org.cloure/clojure]]] + :dependencies + [[org.clojure/clojure "1.7.0-RC1"] + [org.clojure/clojurescript "0.0-3269"] + [figwheel "0.3.3" :exclusions [org.cloure/clojure]] + [org.clojure/core.async "0.1.346.0-17112a-alpha"] + [bardo "0.1.0" :exclusions [org.clojure/clojure]]] + :cljsbuild {:builds + [{:id "example" + :source-paths ["src" "example" + "checkouts/freactive.core/src/clojure" + "checkouts/freactive.core/test"] + :compiler {:output-to "resources/public/js/compiled/app.js" + :output-dir "resources/public/js/compiled/out" + :optimizations :none + :pretty-print true + :source-map true}} + {:id "example-advanced" + :source-paths ["src" "example" "test" "checkouts/freactive.core/src/clojure"] + :compiler {:output-to "resources/public/js/compiled/advanced.js" + :output-dir "resources/public/js/compiled/out-adv" + :optimizations :advanced + :main "freactive.dom-perf"}}]}}} + :source-paths ["src"] + :test-paths ["test" "example"])