Skip to content
Browse files

initial version

  • Loading branch information...
0 parents commit 962f24337f3f338bc37460a17e9153595e1b8ea1 @mjtodd mjtodd committed Apr 18, 2012
Showing with 139 additions and 0 deletions.
  1. +9 −0 .gitignore
  2. +35 −0 README.md
  3. +13 −0 project.clj
  4. +67 −0 src-cljs/cljsbinding.cljs
  5. +15 −0 src/cljsbinding/core.clj
9 .gitignore
@@ -0,0 +1,9 @@
+pom.xml
+*jar
+/lib/
+/classes/
+.lein-deps-sum
+resources/public/cljs/
+.lein-plugins
+.lein-cljsbuild-compiler-0
+resources
35 README.md
@@ -0,0 +1,35 @@
+# cljs-binding
+
+A ClojureScript binding library
+
+cljs-binding makes it easy to bind html elements to ClojureScript functions.
+
+## Examples
+
+### Simple binding
+
+In your view, add an element `[:p {:bind "text: sample.content()"}]`
+
+The paragraphs text will be set to the return value of the `sample.content` javascript/ClojureScript function.
+
+If the ClojureScript sample.content function dereferences any atoms, then when the values of any of those atoms change, the text of the paragraph will be automatically updated.
+
+Multiple bindings can be specified e.g. `[:p {:bind "text: sample.content(); css: sample.contentcss()"}]`
+
+### Binding atoms to inputs
+
+As well as binding UI elements to functions that are dependent on atoms, atoms can also be bound to the value (or more specifically .`val()`) of an input `[:input {:bindatom "sample.MyAtom"}]`. Whenever the input fires the `change` event, the atom will be reset to the new value of the input.
+
+## Usage
+
+Update your project.clj to have a dependency on `fluentsoftware/cljs-binding "1.0.0.SNAPSHOT"`.
+
+The clojure function `cljsbinding.core/init` will generate the appropriate javascript to initialise the cljs-binding client code.
+
+In your ClojureScript code, simply `:require [cljsbinding :as binding]` to ensure that cljsbinding client code is compiled in.
+
+
+## License
+
+Copyright © 2012 Fluent Software Solutions Ltd
+
13 project.clj
@@ -0,0 +1,13 @@
+(defproject fluentsoftware/cljs-binding "1.0.0-SNAPSHOT"
+ :description "ClojureScript binding library"
+ :dependencies [[org.clojure/clojure "1.3.0"]]
+ :dev-dependencies [[lein-cljsbuild "0.1.8"]]
+ :plugins [[lein-cljsbuild "0.1.8"]]
+ :hooks [leiningen.cljsbuild]
+ :cljsbuild {
+ :builds [{:source-path "src-cljs"
+ :jar true
+ :compiler {:output-to "resources/public/js/cljsbinding.js"
+ :optimizations :whitespace
+ :pretty-print true}}]}
+ )
67 src-cljs/cljsbinding.cljs
@@ -0,0 +1,67 @@
+(ns cljsbinding
+ (:use [jayq.core :only [$ attr val change]])
+)
+
+(def BindMonitor (atom false))
+(def BindDependencies (atom {}))
+(def BindFn (atom nil))
+
+(defn translate [data]
+ (if (map? data) (make-js-map data) data)
+)
+
+(defn bind-elem [elem data]
+ (let [f #(.call (aget elem (first data)) elem (translate(js/eval (second data))))]
+ (reset! BindMonitor true)
+ (reset! BindFn f)
+ (f)
+ (reset! BindMonitor false)
+))
+
+(defn make-js-map
+ "makes a javascript map from a clojure one"
+ [cljmap]
+ (let [out (js-obj)]
+ (doall (map #(aset out (name (first %)) (second %)) cljmap))
+ out))
+
+(defn bind [elem]
+ (doseq [data (.split (attr elem "bind") ";")] (bind-elem elem (.split data ":")))
+)
+
+(defn bindatom [elem]
+ (bind-elem elem ["val" (str "cljs.core.deref.call(null," (attr elem "bindatom") ")") ])
+ (.change elem #(
+ (reset! (js/eval (attr elem "bindatom")) (.val elem))
+ :false
+ ))
+)
+
+(defn ^:export init []
+ (doseq [elem ($ "*[bind]")] (bind elem))
+ (doseq [elem ($ "*[bindatom]")] (bindatom elem))
+ )
+
+(defn seq-contains?
+ "Determine whether a sequence contains a given item"
+ [sequence item]
+ (if (empty? sequence)
+ false
+ (reduce #(or %1 %2) (map #(= %1 item) sequence))))
+
+(defn ^:export register [atom]
+ (reset! BindMonitor false)
+ (swap! BindDependencies
+ #(assoc % atom (if (contains? % atom)
+ (cons @BindFn (% atom))
+ [@BindFn]))
+ )
+ (add-watch atom :binding-watch
+ (fn [key a old-val new-val]
+ (doseq [f (@BindDependencies a)] (f))
+ )
+ )
+ (reset! BindMonitor true)
+)
+
+
15 src/cljsbinding/core.clj
@@ -0,0 +1,15 @@
+(ns cljsbinding.core)
+
+(defn bind []
+ [
+ :script "$(function() {
+ // Bit of a hack to hook into deref for dependency management
+ var deref = cljs.core.deref
+ cljs.core.deref = function (a) {
+ if (deref(cljsbinding.BindMonitor))
+ cljsbinding.register(a)
+ return deref(a)
+ }
+ cljsbinding.init()})
+"]
+)

0 comments on commit 962f243

Please sign in to comment.
Something went wrong with that request. Please try again.