/
macros.clj
64 lines (56 loc) · 1.98 KB
/
macros.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(ns widje.macros
"Widget is a function that return DOM node.
It combines crate (hiccup) template with supporting logic (event handling etc).
Also widget keep track of each instance it creates and provide easy way
to search them.
Example:
(defwidget todo [item] ; widget function name and arguments
[:div.todo ; crate template
:p.-text (:name item)] ;
[text] ; bind elements to vars by role (see widje.role)
(listen text :click ; handle events
(mark-done item)) ;
(def mytodo {:name \"Do stuff\"}) ; model
(todo {:name \"Do stuff\"}) ; render
(find-instance mytodo) ; find todo DOM node by first widget param
")
;; Widget
(defmacro widget
"Basic form, returns anonymous widget function. Similar to 'fn'"
([params tags]
`(widje.macros/widget ~params ~tags []))
([params tags bindings & body]
`(let [keyed?# (seq '~params)
instances# (atom (if keyed?# {} []))
widget-fn# (fn ~params
(let [node# (crate.core/html ~tags)
{:keys ~bindings} node#]
(if keyed?#
(swap! instances# assoc (first ~params) node#)
(swap! instances# conj node#))
~@body
node#))]
(set! (.-_instances widget-fn#) instances#)
widget-fn#)))
(defmacro defwidget
"Defines named widget function. Similar to 'defn'"
([name params tags]
`(widje.macros/defwidget ~name ~params ~tags []))
([name params tags bindings & body]
`(def ~name (widje.macros/widget ~params ~tags ~bindings ~@body))))
(defmacro letwidget
"Similar to 'letfn'"
[widgetspecs & body]
`(let ~(vec (interleave
(map first widgetspecs)
(map #(cons 'widje.macros/widget (rest %)) widgetspecs)))
~@body))
;; Util
(defmacro listen
"(listen a :click
(js/alert \"Hey!\"))"
[elem evt & body]
`(jayq.core/bind ~elem ~evt
(fn [~'event]
(cljs.core/this-as ~'this
~@body))))