Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'feature/scriptjure' into develop

  • Loading branch information...
commit 94c44b047a7195ed28049b0c03406bf91064e153 2 parents f29f5aa + 2361f6c
@alienscience authored
View
4 TODO
@@ -0,0 +1,4 @@
+
+1) Generate .js from datastructures
+2) Move to :require
+3) Have :dest-html, :dest-js protection
View
2  examples/demo.clj
@@ -93,7 +93,7 @@
(route/not-found
(html [:h1 "Page not found"])))
-(def server (atom nil))
+(defonce server (atom nil))
(defn stop []
(if-not (nil? @server)
View
2  examples/enlive-demo.clj
@@ -77,7 +77,7 @@
(route/not-found
"<h1>Page not found</h1>"))
-(def server (atom nil))
+(defonce server (atom nil))
(defn stop []
(if-not (nil? @server)
View
2  examples/jqtdemo.clj
@@ -78,7 +78,7 @@
(route/not-found
(html [:h1 "Page not found"])))
-(def server (atom nil))
+(defonce server (atom nil))
(defn stop []
(if-not (nil? @server)
View
11 project.clj
@@ -1,9 +1,12 @@
(defproject uk.org.alienscience/form-dot-clj "0.0.2"
:description "HTML form display and validation."
- :dependencies [[hiccup "0.2.6"]
- [clj-time "0.1.0-RC1"]]
- :dev-dependencies [[org.clojure/clojure "1.2.0-RC3"]
- [org.clojure/clojure-contrib "1.2.0-RC3"]
+ :dependencies [[org.clojure/clojure "1.2.0"]
+ [org.clojure/clojure-contrib "1.2.0"]
+ [hiccup "0.2.6"]
+ [clj-time "0.1.0-RC1"]
+ [scriptjure "0.1.12"]]
+ :dev-dependencies [[org.clojure/clojure "1.2.0"]
+ [org.clojure/clojure-contrib "1.2.0"]
[swank-clojure "1.2.1"]
[ring/ring-jetty-adapter "0.2.5"]
[compojure "0.4.1"]
View
46 src/form_dot_clj/jquery_tools.clj
@@ -1,29 +1,38 @@
(ns form-dot-clj.jquery-tools
(:require [form-dot-clj.extend :as extend])
- (:use hiccup.core))
+ (:use hiccup.core)
+ (:require [hiccup.page-helpers :as ph])
+ (:require [form-dot-clj.js-dot-clj :as js])
+ (:use clojure.contrib.strint))
;;========== Javascript includes ===============================================
+(defn controls-on-ready
+ "Inserts the javascript to be run on-ready for each control"
+ [form]
+ (apply str
+ (remove nil?
+ (map :on-ready
+ (vals (form :controls))))))
+
+
(defn include-js
"Returns the javascript required to activate jquery-tools for the given
form and form-id e.g
(include-js the-form \"myform\")"
[form form-id]
(html
- [:script{:type "text/javascript"
- :src "http://cdn.jquerytools.org/1.2.3/full/jquery.tools.min.js"}]
+ (ph/include-js "http://cdn.jquerytools.org/1.2.3/full/jquery.tools.min.js")
[:script {:type "text/javascript"}
- "$(document).ready(function() {"
- (str "$(\"#" form-id "\").validator();")
- (for [c (vals (form :controls))
- :let [onr (c :on-ready)]
- :when onr]
- onr)
- "});"]))
-
-
-
+ (js/js
+ [:.ready :$document
+ [:function []
+ [:.validator (js/id form-id)]
+ (controls-on-ready form)]])]))
+
+
+
;;========== Textbox ===========================================================
(defn textbox
@@ -80,10 +89,11 @@
(defn- date-on-ready
[id target-id date-format]
- (str "$('#" id "').dateinput({"
- "format: '" date-format "',"
- "change: function() { $('#" target-id "').val(this.getValue('yyyy-mm-dd')); }"
- "});"))
+ (js/js
+ [:.dateinput (js/id id)
+ {:format (js/quoted date-format)
+ :change [:function []
+ [:.val (js/id target-id) [:.getValue :this "yyyy-mm-dd"]]]}]))
(defn- display-name [name] (str "dis" name))
@@ -118,7 +128,7 @@
;;========== Range-input =======================================================
(def range-on-ready
- (str "$(':range').rangeinput();"))
+ (js/js [:.rangeinput :$:range]))
(defn range-input
"Creates a range input to handle the given field"
View
170 src/form_dot_clj/js_dot_clj.clj
@@ -0,0 +1,170 @@
+
+(ns form-dot-clj.js-dot-clj
+ "Playing with javascript generation"
+ (:use clojure.walk))
+
+(comment
+ [:.ready :$document
+ [:function []
+ [:.validate "$(#myform)"]]])
+
+;; States
+(declare start first-arg rest-args
+ method-call function-def
+ block block-start finish
+ start-map map-entry)
+
+;; External functions used internally
+(declare quoted)
+
+(defn- lazy-fsm
+ ([todo]
+ (lazy-fsm start {:nesting 1} todo))
+ ([state-fn state todo]
+ (lazy-seq
+ (state-fn state todo))))
+
+(defn- convert-keyword [kw]
+ (let [word (name kw)
+ one (first word)
+ two (if (> (.length word) 1)
+ (.substring word 0 2))]
+ (cond
+ (= "$:" two) (str "$(\":" (.substring word 2) "\")")
+ (= "$#" two) (str "$(\"#" (.substring word 2) "\")")
+ (= \$ one) (str "$(" (.substring word 1) ")")
+ :else word)))
+
+(defn- convert [form state]
+ (cond
+ (keyword? form) (convert-keyword form)
+ (string? form) (quoted form)
+ (vector? form) (lazy-fsm start
+ (update-in state [:nesting] inc)
+ form)
+ (map? form) (lazy-fsm start-map
+ (update-in state [:nesting] inc)
+ (seq form))
+ :else form))
+
+(defn- start [state todo]
+ (if (empty? todo)
+ nil
+ (let [item (convert (first todo) state)]
+ (cond
+ (= \. (first item)) (lazy-fsm method-call
+ (assoc state :method item)
+ (rest todo))
+ (= "function" item) (cons item
+ (lazy-fsm function-def
+ state
+ (rest todo)))
+ :else (cons item
+ (lazy-fsm first-arg
+ state
+ (rest todo)))))))
+
+(defn- first-arg [state todo]
+ (if (empty? todo)
+ (cons "()" (lazy-fsm finish state nil))
+ (let [item (convert (first todo) state)]
+ (cons "(" (cons item (lazy-fsm rest-args state (rest todo)))))))
+
+(defn- rest-args [state todo]
+ (if (empty? todo)
+ (cons ")" (lazy-fsm finish state nil))
+ (let [item (convert (first todo) state)]
+ (cons "," (cons item (lazy-fsm rest-args state (rest todo)))))))
+
+(defn- method-call [state todo]
+ (if (empty? todo)
+ "<error>"
+ (let [item (convert (first todo) state)
+ method (state :method)]
+ (cons item
+ (cons method
+ (lazy-fsm first-arg state (rest todo)))))))
+
+(defn- function-def [state todo]
+ (if (empty? todo)
+ "<error>"
+ (let [args (first todo)
+ arg-seq (lazy-fsm first-arg
+ (update-in state [:nesting] inc)
+ args)]
+ (cons arg-seq
+ (lazy-fsm block-start state (rest todo))))))
+
+(defn- block-start [state todo]
+ (if (empty? todo)
+ "{}"
+ (let [block-state (assoc state :nesting 0)
+ item (convert (first todo) block-state)]
+ (cons "{"
+ (cons item
+ (lazy-fsm block block-state (rest todo)))))))
+
+(defn- block [state todo]
+ (if (empty? todo)
+ "}"
+ (let [item (convert (first todo) state)]
+ (cons item
+ (lazy-fsm block state (rest todo))))))
+
+(defn- finish [state todo]
+ (let [nesting (state :nesting)]
+ (if (<= nesting 1)
+ ";")))
+
+(defn- start-map [state todo]
+ (if (empty? todo)
+ "{}"
+ (let [[k v] (first todo)
+ k-item (convert k state)
+ v-item (convert v state)]
+ (cons "{"
+ (cons k-item
+ (cons ": "
+ (cons v-item
+ (lazy-fsm map-entry state (rest todo)))))))))
+
+(defn- map-entry [state todo]
+ (if (empty? todo)
+ "}"
+ (let [[k v] (first todo)
+ k-item (convert k state)
+ v-item (convert v state)]
+ (cons ","
+ (cons k-item
+ (cons ": "
+ (cons v-item
+ (lazy-fsm map-entry state (rest todo)))))))))
+
+;;======== Flatten strings ============
+
+(defn- cat-strings [acc b]
+ (if (and (seq? b) (not (list? b)))
+ (reduce cat-strings acc b)
+ (let [a (peek acc)]
+ (if (and (or (string? a) (char? a) (number? a))
+ (or (char? b) (string? b) (number? b)))
+ (conj (pop acc) (str a b))
+ (conj acc b)))))
+
+(defn- optimise-strings [js-seq]
+ (reduce cat-strings [] js-seq))
+
+(defn- js-sequence [form]
+ (optimise-strings (lazy-fsm form)))
+
+(defmacro js [form]
+ (let [j (js-sequence form)]
+ `(str ~@j)))
+
+(defn id [value]
+ (str "$(\"#" value "\")"))
+
+(defn quoted
+ "Quote the given string"
+ [s]
+ (str "\"" s "\""))
Please sign in to comment.
Something went wrong with that request. Please try again.