enfocus
文件大小: unknow
源码售价: 5 个金币 积分规则     积分充值
资源说明:DOM manipulation and templating library for ClojureScript inspired by Enlive.
# Enfocus

Enfocus is a `DOM` manipulation and templating library for
ClojureScript. Inspired by Christophe Grand's [Enlive][1], Enfocus'
primary purpose is providing a base for building rich interfaces in
ClojureScript.

If you are unfamiliar with enlive I also recommend taking a look at
these links.

David Nolen wrote a [nice tutorial][2]

Another [tutorial][3] by Brian Marick.


# Documentation & Examples

[Documentation & Demo Site][4]

[Example Website][5]

# Where do I get support?

[On the group][6]

# Quick Start

## Setup

From any leiningen project file:

[![Clojars Project](http://clojars.org/enfocus/latest-version.svg)](http://clojars.org/enfocus)

For the best development experience, use [lein-cljsbuild][7]

### The Basics

Every great journey starts with "Hello world!"

```clj
(ns my.namespace
  (:require [enfocus.core :as ef]
            [enfocus.events :as events]
	    [enfocus.effects :as effects])
  (:require-macros [enfocus.macros :as em]))

(defn start []
  (ef/at js/document
    ["body"] (ef/content "Hello enfocus!")))

(set! (.-onload js/window) start)
```

See [hello-enfocus][15] repo.

## The `at` form

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:

A single transform

```clj
(at a-node (transform arg1 ...))

;or with implied js/document

(at selector (transform arg1 ...))
```

and a series of transforms

```clj
(at a-node
    [selector1] (transform1 arg1 ...)
    [selector2] (transform2 arg1 ...))

;or with implied js/document

(at [selector1] (transform1 arg1 ...)
    [selector2] (transform2 arg1 ...))
```

In the first case `at` is passed a node, node set or selector and a
transform.  This form of `at` calls the transform on each element in
the node set.

A `transform` is nothing more than a function that takes a set of
arguments and returns a function that takes a set of nodes.  In case
of the `"Hello World!"` example above, we see the use of `(em/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 and a set of selector/transform pairs. The selectors are scoped by
the node, node set or js/document, if a node is not passed in, and the
results of each selector is passed on to its partner transformation.

A `selector` is a string representing a [CSS3 compliant selector][8]

### Handling Events

Enfocus has event handling.  Below is a simple example to add an
`onclick` event handler to a button.

```clj
(em/defaction change [msg]
  ["#button1"] (ef/content msg))

(em/defaction setup []
  ["#button1"] (events/listen :click #(change "I have been clicked")))

(set! (.-onload js/window) setup)
```

The `defaction` construct is use here instead `defn`.  `defaction`
creates a function that calls the `at` form like discussed above and
passes in `js/document` as the node to be transformed.

### Effects

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.

```clj
(em/defaction resize-div [width]
  ["#rz-demo"] (effects/chain
                 (effects/resize width :curheight 500 20)
                 (effects/resize 5 :curheight 500 20)))

(em/defaction setup []
  ["#button2"] (events/listen #(resize-div 200)))

(set! (.-onload js/window) setup)
```

### Actions, templates and snippets

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.

```clj
(em/defsnippet snippet2 "templates/template1.html" ["tbody > *:first-child"]
               [fruit quantity]
               ["tr > *:first-child"] (ef/content fruit)
               ["tr > *:last-child"] (ef/content (str quantity)))
```

A template is very similar to a snippet 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.

```clj
(em/deftemplate template2 "/templates/template1.html" [fruit-data]
                ["#heading1"] (ef/content "fruit")
                ["thead tr > *:last-child"] (ef/content "quantity")
                ["tbody"] (ef/content
                           (map #(snippit2 % (fruit-data %)) (keys fruit-data))))
```

Normally, snippets and templates are loaded via an AJAX request, but
you can also create `:compiled` templates, which will be inlined in to
resulting code at compile time:

```clj
(em/deftemplate template2 :compiled "/templates/template1.html" [fruit-data]
                ["#heading1"] (ef/content "fruit")
                ["thead tr > *:last-child"] (ef/content "quantity")
                ["tbody"] (ef/content
                           (map #(snippit2 % (fruit-data %)) (keys fruit-data))))
```

If, snippets and/or templates are loaded via AJAX it is important to
make sure the content has been loaded before calling the template or
snippit function.  Enfocus provides a convient macro that works like
an onload callback but for AJAX driven snippets and templates.

```clj
(em/wait-for-load (render-page))
```

An action is a set of transforms that take place on the live dom.
below is a definition of a an action.

```clj
(em/defaction action2 []
             [".cool[foo=false]"] (ef/content (template2 {"banana" 5 "pineapple" 10}))
             ["#heading1"] (ef/set-attr :id "new-heading1"))
```

Enfocus also support [hiccup][11] style emitters introduced in
[enlive "1.1.0"][1].

```clj
(defn hiccup-template [arg1]
  (ef/html
    [:h1#hiccup.clazz {:width arg1} "Hiccup Emitters are Cool"]))
```

## Transformations

A transformation is a function that returns either a node or
collection of node.

### Enfocus defines several helper functions for transformations:

Supported Enlive Transformations

```clj
  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")
  clone-for          (clone-for [item items] transformation)
                     or (clone-for [item items]
                          selector1 transformation1
                          selector2 transformation2)
  wrap               (wrap :div) or (wrap :div {:class "foo"})
  unwrap             (unwrap)
  replace-vars       (replace-vars {:var1 "value" :var2 "value")
```

New Transformations

```clj
  focus              (focus)
  blur               (blur)
  set-prop           (set-prop :value "testing")
  set-style          (set-style :font-size "10px" :background "#fff")
  remove-style       (remove-style :font-size :background)
  listen             (listen :mouseover (fn [event] ...))
  remove-listeners   (remove-listeners :mouseover :mouseout)
  fade-in            (fade-in time)
                     or (fade-in time callback)
                     or (fade-in time callback accelerator)
  fade-out           (fade-out time)
                     or (fade-out time callback)
  resize             (resize width height ttime)
                     or (resize width height ttime callback)
                     or (resize width height ttime callback accelerator)
  move               (move x y ttime)
                     or (move x y ttime callback)
                     or (move x y ttime callback accelerator)
  scroll             (scroll x y ttime)
  		     or (scroll x y ttime callback)
		     or (scroll x y ttime callback accelerator)
  chain              (chain (fade-in ttime) ;serialize async effects
                            (move x y ttime)
                            (fade-out ttime)
                            ...)
  set-data           (set-data key value)
```

Currently there is one transformation that is supported by Enlive but
not Enfocus. (Patches very welcome!!)

```clj
  move               (move [:.footnote] [:#footnotes] content)
                     ;this will be called relocate in enfocus
```


## Selectors

Enfocus supports both [CSS3][8] and [XPath][12] selectors:

```clj
(ns example
  (:require [enfocus.core :as ef])
  (:require-macros [enfocus.macros :as em]))

(em/defaction action2 []
             [".cool[foo=false]"] (ef/content ....)) ;CSS3
             (ef/xpath "//tr[@id='1']/th[2]") (ef/set-attr :id "new-heading1")) ;XPATH
```


## The `from` form

The `from` form is how we get data from the dom in enfocus.  It comes
in two basic flavors listed below:

This form returns the result of the extractor.

```clj
(from a-node (extractor arg1 ...))

;or with selector

(from selector (extractor arg1 ...))
```

and this form returns a map of the form `{:key1 result1 :key2 result2}`

```clj
(from a-node
    :key1 [selector1] (extractor arg1 ...)
    :key2 [selector2] (extractor arg1 ...))

;or implied js/documnt

(from
    :key1 [selector1] (extractor arg1 ...)
    :key2 [selector2] (extractor arg1 ...))
```


## Extractors

An extractor is a function that takes a node and returns information
about.

### Enfocus defines several helper fuctions for extractors:

An extractor is a funciton that takes a node and returns information about

```clj
  get-attr           (get-attr :attr1)
  get-text           (get-text)
  get-prop           (get-prop :value)
  get-data           (get-data :key1)
  read-form          (read-form)  - returns {:field1 ("val1" "val2") :field2 val}
```

## Contributing

* Download [leiningen][9]

### Compile Enfocus

```bash
 git clone git://github.com/ckirkendall/enfocus.git
 cd enfocus
 lein do cljx once, compile
```

### Test Enfocus

After having compiled down `enfocus` as explained above

```bash
lein test
```

### bREPLing with Enfocus

After having compiled down `enfocus` as explained above issue the
following `lein` task:

```bash
 lein repl
```

Then run the http server as follows

```clj
user=> (run)
2013-10-15 12:34:33.082:INFO:oejs.Server:jetty-7.6.8.v20121106
2013-10-15 12:34:33.138:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:3000
#
```

Next launch the browser-connected REPL as follows:

```clj
user=> (browser-repl)
Browser-REPL ready @ http://localhost:55211/4347/repl/start
Type `:cljs/quit` to stop the ClojureScript REPL
nil
cljs.user=>
```

Finally, visit the [http://localhost:3000/][10] URI

The page is empty and it used for bREPLin only. Wait few moments while
the connection is established and then you can start bREPLing with
Enfocus.

```clj
cljs.user=> (js/alert "Hello, Enfocus!")
```

### Final note

All the [Austin][16] use cases should work as expected.

## License

Copyright (C) 2012-2013 Creighton Kirkendall

Distributed under the Eclipse Public License, the same as Clojure.

## Special Thanks!

[Christophe Grand][14] for creating [enlive][1] and building a simple
api for dom manipulation.

[1]: http://github.com/cgrand/enlive
[2]: http://github.com/swannodette/enlive-tutorial/
[3]: https://github.com/cgrand/enlive/wiki/Table-and-Layout-Tutorial,-Part-1:-The-Goal
[4]: http:/ckirkendall.github.com/enfocus-site
[5]: http://github.com/ckirkendall/The-Great-Todo
[6]: http://groups.google.com/group/enfocus
[7]: https://github.com/emezeske/lein-cljsbuild
[8]: http://www.w3schools.com/cssref/css_selectors.asp
[9]: https://github.com/technomancy/leiningen
[10]: http://localhost:3000/
[11]: https://github.com/weavejester/hiccup
[12]: http://www.w3schools.com/xpath/xpath_syntax.asp
[13]: https://github.com/cemerick/piggieback
[14]: https://github.com/cgrand
[15]: https://github.com/magomimmo/hello-enfocus
[16]: https://github.com/cemerick/austin

本源码包内暂不包含可直接显示的源代码文件,请下载源码包。