Enfocus is a DOM
manipulation and templating library for ClojureScript. Inspired by Christophe Grand’s Enlive, Enfocus’ primary purpose is providing a base for building rich interfaces in ClojureScript.
If you are unfamiliar with enlive it is suggested you take a look at the following tutorials before diving into Enfocus.
David Nolen wrote a nice tutorial
Another tutorial by Brian Marick.
A snippet is a function that returns a seq of nodes, it can be used as a
building block for more complex templates or actions.
You define a snippet by providing a remote resource, a selector and series of transformations.
The snippet definition below selects a table body from the remote resource
templates/template1.html and grabs the first row. It then fills the content of the row.
(em/defsnippet snippet2 "templates/template1.html" ["tbody > *:first-child"] [fruit quantity] ["tr > *:first-child"] (em/content fruit) ["tr > *:last-child"] (em/content (str quantity)))
A template is very similar to a snippit except it does not require a selector to
grap a sub section, instead the entire remote resource is used as the dom.
If the remote resource is a full html document only what is inside the body tag is
brought into the template.
(em/deftemplate template2 "/templates/template1.html" [fruit-data] ["#heading1"] (em/content "fruit") ["thead tr > *:last-child"] (em/content "quantity") ["tbody"] (em/content (map #(snippit2 % (fruit-data %)) (keys fruit-data))))
An action is a set of transforms that take place on the live dom. below is a
definition of a an action.
(em/defaction action2 [] [".cool[foo=false]"] (em/content (template2 {"bannan" 5 "pineapple" 10})) ["#heading1"] (em/set-attr :id "new-heading1"))
The at
form is a very important form in Enfocus and in Enlive. There are implicit at
forms in action
, snippet
and template
.
(at a-node [:a :selector] a-transformation [:another :selector] another-transformation ...)
Transformations are closures which take one arg (the selected node) and return
nil, another node or an arbitrarily nested collection of nodes.
Rules are applied top-down: the first rule transforms the whole tree and the
resulting tree is passed to the next rules.
A transformation is a function that returns either a node or collection of node.
Supported Enlive Transformations
content (content “xyz” a-node “abc”)
html-content (html-content “please no”)
set-attr (set-attr :attr1 “val1” :attr2 “val2”)
remove-attr (remove-attr :attr1 :attr2)
add-class (add-class “foo” “bar”)
remove-class (remove-class “foo” “bar”)
do→ (do→ transformation1 transformation2)
append (append “xyz” a-node “abc”)
prepend (prepend “xyz” a-node “abc”)
after (after “xyz” a-node “abc”)
before (before “xyz” a-node “abc”)
substitute (substitute “xyz” a-node “abc”)
New Transformations
set-style (set-style :font-size “10px” :background “#fff”)
remove-style (remove-style :font-size :background)
add-event (add-event :mouseover (fn [event] …))
remove-event (remove-event :mouseover :mouseout)
fade-in (fade-in time step-size)
fade-out (fade-out time step-size)
resize (resize width height ttime step-size)
move (move x y ttime step-size)
Currently there are several transformation that are supported by Enlive but not Enfocus. (Patches very welcome!!)
wrap (wrap :div) or (wrap :div {:class "foo"})
unwrap unwrap
clone-for (clone-for [item items] transformation)
or (clone-for [item items]
selector1 transformation1
selector2 transformation2)
move (move [:.footnote] [:#footnotes] content)
- Download lieningen
- Download & Install cljs-watch
- Make sure that you have your CLOJURESCRIPT_HOME path setup correctly
- Also ensure that your lib has the goog-jar.jar that comes with cljs-watch
Compile ClojureScript
git clone git://github.com/ckirkendall/enfocus.git
cd enfocus/project
cljs-watch cljs-src/ ‘{:output-dir “../sample/resources/public/cljs” :output-to “../sample/resources/public/cljs/enfocus.js”}’
git clone git://github.com/ckirkendall/enfocus.git
cd enfocus/project
cljs-watch cljs-src/ ‘{:output-dir “../sample/resources/public/cljs” :output-to “../sample/resources/public/cljs/enfocus.js”}’
Viewing the Test Page
cd enfocus/sample
lein deps
lein repl
=>(use ’ring.adapter.jetty)
=>(use ’enfocus.ring)
=>(run-jetty app {:port 3000})
cd enfocus/sample
lein deps
lein repl
=>(use ’ring.adapter.jetty)
=>(use ’enfocus.ring)
=>(run-jetty app {:port 3000})
Open your browser to:
http://localhost:3000/test.html
Christophe Grand for creating enlive and building a simple api for dom manipulation.