Skip to content

Instantly share code, notes, and snippets.

@aav
Created June 29, 2015 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aav/072b78c69ad1166b0cb6 to your computer and use it in GitHub Desktop.
Save aav/072b78c69ad1166b0cb6 to your computer and use it in GitHub Desktop.
(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