The quickest way to get up and running is to use the enfocus-template. This is a Leiningen template that creates a sample app for using enfocus and ring.
Creating your application:
lein new enfocus-template my-app
Launching your applications:
cd my-app lein cljsbuild once lein ring server
This should launch the app into a browser.
[enfocus "2.0.0-SNAPSHOT"]
For the best development experience, use lein-cljsbuild.
(ns my.namespace (:require [enfocus.core :as ef]) (:require-macros [enfocus.macros :as em])) (defn start [] (ef/at "body" (ef/content "Hello world!")) (set! (.-onload js/window) start)
At the core to understanding Enfocus is the at form used in the "Hello world!" example above. It comes in two basic flavors listed below:
Single Transform
(at a-node (transform arg1 ...)) ;or implied js/document as main node (at "selector" (transfrom arg1 ...))
Multiple Transforms
(at a-node "selector1" (transform1 arg1 ...) "selector2" (transform2 arg1 ...)) ;or implied js/document as main node (at "selector1" (transform1 arg1 ...) "selector2" (transform2 arg1 ...))
In the first case, at is passed a node/node set or a selector, and a transform and calls the transform on each element in the node set. If a selector is passed the root node is defaulted to js/document.
A transform is nothing more than a function that takes a set of arguments and returns a function that takes a node. In case of the "Hello World!" example above, we see the use of (ef/content "Hello world!"). This call returns a function that takes node or node set and replaces the content with "Hello world!"
In the second case, we see at is optionally passed a node or node set followed by selector/transform pairs. The selectors are scoped by the node or node set, if provided or js/document otherwise, and the results of each selector is passed on to its partner transformation.
A selector is a string representing a CSS3 compliant selector.
Lets look at handling events. When we click the button it will change to say "I have been clicked."
HTML:
<html> <body> <button id="button1">click me</button> </body> </html>CLJS:
(em/defaction change [msg] "#button1" (ef/content msg)) (em/defaction setup [] "#button1" (ef/listen :click #(change "I have been clicked"))) (set! (.-onload js/window) setup)
The defaction construct is use here instead of defn. defaction creates a function that calls the at form like discussed above and passes in js/document as the node to be transformed.
Enfocus has the concept of effects. Effects are nothing more than transformations over a period of time. Below is a simple example of a resize effect. Notice how the effects can be chained.
HTML:
<html> <body> <div id="rz-demo" style="width: 5px; height: 10px; background-color: #33ff33;"> </div> <button id="button2">click me</button> </body> </html>
CLJS:
(em/defaction resize-div [width] "#rz-demo" (ef/chain (ef/resize width :curheight 500) (ef/resize 5 :curheight 500))) (em/defaction setup [] "#button2" (ef/listen #(resize-div 200))) (set! (.-onload js/window) setup)
Example:
fruit | quantity |
---|---|
replace | me |
The following action is triggered when we click the button.
(defn clone-for-demo [] (let [fruit-data {"apple" 5, "pear" 6}] (ef/at "#clone-for-demo tbody > tr:first-child" (ef/clone-for [fr (vec fruit-data)] "*:first-child" (ef/content (first fr)) "*:last-child" (ef/content (str (second fr)))))))
Below is an example of using the from form with the read-form extractor.
Example:
The following action is triggered when we click the button.
(defn get-prop-demo [] (let [values (ef/from "#read-form-test" (ef/read-form))] (ef/at "#read-form-demo" (ef/content (pr-str values)))))