-
-
Save aav/072b78c69ad1166b0cb6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns vdom.main | |
(:require | |
[cljs.core.async :as async]) | |
(:require-macros | |
[cljs.core.async.macros :refer [go go-loop]])) | |
(defn build [form] | |
(let [tag (first form) props (second form) children (drop 2 form)] | |
(.h js/virtualDom (name tag) (clj->js props) | |
(clj->js | |
(map | |
(fn [form] | |
(cond | |
(string? form) form | |
(vector? form) | |
(build form))) | |
(mapcat | |
(fn [e] (if (seq? e) e [e])) children)))))) | |
(defn mount [target model view ctrl] | |
(let [updates (async/chan 1) | |
vnode (build (view updates model)) | |
dnode (.create js/virtualDom vnode)] | |
(.appendChild target dnode) | |
(go-loop [model model vnode vnode dnode dnode] | |
(when-let [update (<! updates)] | |
(let [model (ctrl model) | |
new-vnode (build (view updates model)) | |
diff (.diff js/virtualDom vnode new-vnode) | |
new-dnode (.patch js/virtualDom dnode diff)] | |
(recur model new-vnode new-dnode)))) updates)) | |
; ------------------------------------ | |
(def colors ["red" "green" "blue" "pink" "magenta" "black" "yellow"]) | |
(defn random-colors [n] | |
(take n (repeatedly #(rand-int (count colors))))) | |
(def m | |
(let [rows 50 cols 5] | |
{:rows rows :cols cols :size 30 :data (random-colors (* rows cols))})) | |
(defn v [updates {:keys [rows cols size data]}] | |
(let [rcs (for [row (range rows) col (range cols) ] [col row])] | |
[:div {} | |
(map | |
(fn [[col row] clr] | |
[:div {:onclick #(go (>! updates true)) | |
:style {:position "fixed" | |
:border "1px solid" | |
:background-color (nth colors clr) | |
:width (str size "px") :height (str size "px") | |
:top (str (* row size) "px") :left (str (* col size) "px")}} ""]) rcs data)])) | |
(defn c [{:keys [cols colors data] :as model}] | |
(let [new (random-colors cols)] | |
(assoc model :data | |
(concat new (drop-last cols data))))) | |
(defn main [target] | |
(let [updates (mount target m v c)] | |
(.setInterval js/window | |
#(go (>! updates true)) 100))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment