Skip to content

Instantly share code, notes, and snippets.

@jonase
Created February 5, 2012 21:47
Show Gist options
  • Save jonase/1748079 to your computer and use it in GitHub Desktop.
Save jonase/1748079 to your computer and use it in GitHub Desktop.
Remove ClojureScript One sample app and add a very simple application stub
From 22694b6e3d0ae4fe9c649deead0127073bf3c7c9 Mon Sep 17 00:00:00 2001
From: Jonas Enlund <[email protected]>
Date: Sun, 5 Feb 2012 18:09:07 +0200
Subject: [PATCH] Skeleton app
---
project.clj | 2 +-
public/design.html | 4 -
src/app/clj/newapp/config.clj | 27 +++++
src/app/clj/newapp/dev_server.clj | 67 ++++++++++++
src/app/clj/newapp/prod_server.clj | 27 +++++
src/app/clj/newapp/repl.clj | 36 +++++++
src/app/clj/one/sample/api.clj | 33 ------
src/app/clj/one/sample/config.clj | 30 -----
src/app/clj/one/sample/dev_server.clj | 98 -----------------
src/app/clj/one/sample/prod_server.clj | 29 -----
src/app/clj/one/sample/repl.clj | 36 -------
src/app/cljs-macros/one/sample/snippets.clj | 15 ---
src/app/cljs/newapp/core.cljs | 32 ++++++
src/app/cljs/one/sample/animation.cljs | 139 ------------------------
src/app/cljs/one/sample/controller.cljs | 70 ------------
src/app/cljs/one/sample/core.cljs | 33 ------
src/app/cljs/one/sample/history.cljs | 23 ----
src/app/cljs/one/sample/logging.cljs | 26 -----
src/app/cljs/one/sample/model.cljs | 152 ---------------------------
src/app/cljs/one/sample/view.cljs | 150 --------------------------
templates/application.html | 18 +---
templates/form.html | 17 ---
templates/greeting.html | 11 --
templates/toolbar.html | 18 ++--
24 files changed, 202 insertions(+), 891 deletions(-)
create mode 100644 src/app/clj/newapp/config.clj
create mode 100644 src/app/clj/newapp/dev_server.clj
create mode 100644 src/app/clj/newapp/prod_server.clj
create mode 100644 src/app/clj/newapp/repl.clj
delete mode 100644 src/app/clj/one/sample/api.clj
delete mode 100644 src/app/clj/one/sample/config.clj
delete mode 100644 src/app/clj/one/sample/dev_server.clj
delete mode 100644 src/app/clj/one/sample/prod_server.clj
delete mode 100644 src/app/clj/one/sample/repl.clj
delete mode 100644 src/app/cljs-macros/one/sample/snippets.clj
create mode 100644 src/app/cljs/newapp/core.cljs
delete mode 100644 src/app/cljs/one/sample/animation.cljs
delete mode 100644 src/app/cljs/one/sample/controller.cljs
delete mode 100644 src/app/cljs/one/sample/core.cljs
delete mode 100644 src/app/cljs/one/sample/history.cljs
delete mode 100644 src/app/cljs/one/sample/logging.cljs
delete mode 100644 src/app/cljs/one/sample/model.cljs
delete mode 100644 src/app/cljs/one/sample/view.cljs
delete mode 100644 templates/form.html
delete mode 100644 templates/greeting.html
diff --git a/project.clj b/project.clj
index 7153f58..4915d17 100644
--- a/project.clj
+++ b/project.clj
@@ -14,7 +14,7 @@
"886d8dc81812962d30a741d6d05ce9d90975160f"]
["https://github.com/levand/domina.git"
"8933b2d12c44832c9bfaecf457a1bc5db251a774"]]
- :repl-init one.sample.repl
+ :repl-init newapp.repl
:source-path "src/app/clj"
:extra-classpath-dirs [".lein-git-deps/clojurescript/src/clj"
".lein-git-deps/clojurescript/src/cljs"
diff --git a/public/design.html b/public/design.html
index d57570d..b58e079 100644
--- a/public/design.html
+++ b/public/design.html
@@ -22,10 +22,6 @@
in <code>src/app/cljs-macros/one/sample/snippets.clj</code>. Changing
these files will update the views in the ClojureScript application.
</p>
- <ul>
- <li><a href="/design/form.html">Form</a></li>
- <li><a href="/design/greeting.html">Greeting</a></li>
- </ul>
</div>
</div>
diff --git a/src/app/clj/newapp/config.clj b/src/app/clj/newapp/config.clj
new file mode 100644
index 0000000..83a3098
--- /dev/null
+++ b/src/app/clj/newapp/config.clj
@@ -0,0 +1,27 @@
+(ns newapp.config
+ "Contains configuration for the newapp application."
+ (:require [net.cgrand.enlive-html :as html]))
+
+(defn- production-transform [h]
+ (html/transform h
+ [:ul#navigation]
+ (html/substitute (html/html-snippet ""))))
+
+(def ^{:doc "Configuration for the newapp application."}
+ config {:src-root "src"
+ :app-root "src/app/cljs"
+ :top-level-package "one"
+ :js "public/javascripts"
+ :dev-js-file-name "main.js"
+ :prod-js-file-name "mainp.js"
+ :dev-js ["goog.require('newapp.core');"
+ "goog.require('newapp.view');"
+ "newapp.core.start();newapp.core.repl();"]
+ :prod-js ["newapp.core.start();"]
+ :reload-clj ["/one/host_page"
+ "/one/reload"
+ "/one/templates"]
+ ;; "/one/sample/api"
+ ;; "/one/sample/config"
+ ;; "/one/sample/dev_server"]
+ :prod-transform production-transform})
diff --git a/src/app/clj/newapp/dev_server.clj b/src/app/clj/newapp/dev_server.clj
new file mode 100644
index 0000000..f03a2e9
--- /dev/null
+++ b/src/app/clj/newapp/dev_server.clj
@@ -0,0 +1,67 @@
+(ns newapp.dev-server
+ "Serve a friendly ClojureScript environment with code reloading and
+ the ClojureScript application in both development and advanced
+ compiled mode."
+ (:use [ring.adapter.jetty :only (run-jetty)]
+ [ring.middleware.file :only (wrap-file)]
+ [ring.middleware.file-info :only (wrap-file-info)]
+ [ring.middleware.params :only (wrap-params)]
+ [ring.middleware.stacktrace :only (wrap-stacktrace)]
+ [ring.util.response :only (file-response)]
+ [compojure.core :only (defroutes GET POST ANY)]
+ [cljs.repl :only (repl)]
+ [cljs.repl.browser :only (repl-env)]
+ [one.templates :only (load-html apply-templates render)]
+ [one.host-page :only (application-host)]
+ [newapp.config])
+ (:require [net.cgrand.enlive-html :as html]
+ [one.reload :as reload])
+ (:import java.io.File))
+
+(defn- environment [uri]
+ (if (= uri "/development") :development :production))
+
+(defn- make-host-page [request]
+ {:status 200
+ :headers {"Content-Type" "text/html; charset=utf-8"}
+ :body (application-host config (environment (:uri request)))})
+
+(defroutes app-routes
+ (GET "/development" request (make-host-page request))
+ (GET "/production" request (make-host-page request) )
+ (GET "/design*" {{file :*} :route-params}
+ (when (.endsWith file ".html")
+ (load-html (.substring file 1))))
+ (ANY "*" request (file-response "404.html" {:root "public"})))
+
+(defn- js-encoding [handler]
+ (fn [request]
+ (let [{:keys [headers body] :as response} (handler request)]
+ (if (and (= (get headers "Content-Type") "text/javascript")
+ (= (type body) File))
+ (assoc-in response [:headers "Content-Type"]
+ "text/javascript; charset=utf-8")
+ response))))
+
+(defn- rewrite-design-uris [handler]
+ (fn [{:keys [uri] :as request}]
+ (if (some true? (map #(.startsWith uri (str "/design/" %))
+ ["css" "javascripts" "images" "js" "favicon.ico"]))
+ (handler (assoc request :uri (.substring uri 7)))
+ (handler request))))
+
+(def ^:private app (-> app-routes
+ (reload/watch-cljs config)
+ (wrap-file "public")
+ rewrite-design-uris
+ wrap-file-info
+ apply-templates
+ js-encoding
+ wrap-params
+ wrap-stacktrace
+ (reload/reload-clj (:reload-clj config))))
+
+(defn run-server
+ "Start the development server on port 8080."
+ []
+ (run-jetty (var app) {:join? false :port 8080}))
diff --git a/src/app/clj/newapp/prod_server.clj b/src/app/clj/newapp/prod_server.clj
new file mode 100644
index 0000000..eaf6714
--- /dev/null
+++ b/src/app/clj/newapp/prod_server.clj
@@ -0,0 +1,27 @@
+(ns one.sample.prod-server
+ "Production server serves the backend API. This is only required if
+ there is a backend API."
+ (:use [ring.adapter.jetty :only (run-jetty)]
+ [ring.middleware.file :only (wrap-file)]
+ [ring.middleware.file-info :only (wrap-file-info)]
+ [ring.middleware.params :only (wrap-params)]
+ [ring.util.response :only (file-response)]
+ [compojure.core :only (defroutes ANY)]))
+
+(def ^:private root "out/public")
+
+;; HACK: Something about the defroutes below requires that the
+;; out/public directory exist, or we get a compile error.
+(.mkdirs (java.io.File. "out/public"))
+
+(defroutes app-routes
+ (-> (ANY "*" request (file-response "404.html" {:root root}))
+ (wrap-file root)
+ wrap-file-info))
+
+(def ^:private app (-> app-routes
+ wrap-params))
+
+(defn run-server []
+ (let [port (Integer/parseInt (get (System/getenv) "PORT" "8080"))]
+ (run-jetty (var app) {:join? false :port port})))
diff --git a/src/app/clj/newapp/repl.clj b/src/app/clj/newapp/repl.clj
new file mode 100644
index 0000000..3ac26f5
--- /dev/null
+++ b/src/app/clj/newapp/repl.clj
@@ -0,0 +1,36 @@
+(ns newapp.repl
+ "The starting namespace for the project. This is the namespace that
+ users will land in when they start a Clojure REPL. It exists to
+ provide convenience functions like 'go' and 'dev-server'."
+ (:use [clojure.repl])
+ (:require [one.tools :as tools]
+ [newapp.dev-server :as dev]
+ [clojure.java.browse :as browse]))
+
+(defn go
+ "Start a browser-connected REPL and launch a browser to talk to it."
+ []
+ (dev/run-server)
+ (future (Thread/sleep 3000)
+ (browse/browse-url "http://localhost:8080/development"))
+ (tools/cljs-repl))
+
+(defn dev-server
+ "Start the development server and open the host application in the
+ default browser."
+ []
+ (dev/run-server)
+ (future (Thread/sleep 3000)
+ (browse/browse-url "http://localhost:8080")))
+
+;; This is a convenience function so that people can start a CLJS REPL
+;; without having to type in (tools/cljs-repl)
+(defn cljs-repl
+ "Start a ClojureScript REPL."
+ []
+ (tools/cljs-repl))
+
+(println)
+(println "Type (go) to launch the development server and setup a browser-connected REPL.")
+(println "Type (dev-server) to launch only the development server.")
+(println)
diff --git a/src/app/clj/one/sample/api.clj b/src/app/clj/one/sample/api.clj
deleted file mode 100644
index 607d78d..0000000
--- a/src/app/clj/one/sample/api.clj
+++ /dev/null
@@ -1,33 +0,0 @@
-(ns one.sample.api
- "The server side of the sample application. Provides a simple API for
- updating an in-memory database."
- (:use [compojure.core :only (defroutes POST)]))
-
-(defonce ^:private next-id (atom 0))
-
-(defonce ^:dynamic *database* (atom #{}))
-
-(defmulti remote
- "Multimethod to handle incoming API calls. Implementations are
- selected based on the :fn key in the data sent by the client.
- Implementation are called with whatever data struture the client
- sends (which will already have been read into a Clojure value) and
- can return any Clojure value. The value the implementation returns
- will be serialized to a string before being sent back to the client."
- :fn)
-
-(defmethod remote :default [data]
- {:status :error :message "Unknown endpoint."})
-
-(defmethod remote :add-name [data]
- (let [n (-> data :args :name)
- response {:exists (contains? @*database* n)}]
- (swap! *database* conj n)
- response))
-
-(defroutes remote-routes
- (POST "/remote" {{data "data"} :params}
- (pr-str
- (remote
- (binding [*read-eval* false]
- (read-string data))))))
diff --git a/src/app/clj/one/sample/config.clj b/src/app/clj/one/sample/config.clj
deleted file mode 100644
index 9aa6d94..0000000
--- a/src/app/clj/one/sample/config.clj
+++ /dev/null
@@ -1,30 +0,0 @@
-(ns one.sample.config
- "Contains configuration for the sample application."
- (:require [net.cgrand.enlive-html :as html]))
-
-(defn- production-transform [h]
- (html/transform h
- [:ul#navigation]
- (html/substitute (html/html-snippet ""))))
-
-(def ^{:doc "Configuration for the sample application."}
- config {:src-root "src"
- :app-root "src/app/cljs"
- :top-level-package "one"
- :js "public/javascripts"
- :dev-js-file-name "main.js"
- :prod-js-file-name "mainp.js"
- :dev-js ["goog.require('one.sample.core');"
- "goog.require('one.sample.model');"
- "goog.require('one.sample.controller');"
- "goog.require('one.sample.history');"
- "goog.require('one.sample.logging');"
- "one.sample.core.start();one.sample.core.repl();"]
- :prod-js ["one.sample.core.start();"]
- :reload-clj ["/one/host_page"
- "/one/reload"
- "/one/templates"
- "/one/sample/api"
- "/one/sample/config"
- "/one/sample/dev_server"]
- :prod-transform production-transform})
diff --git a/src/app/clj/one/sample/dev_server.clj b/src/app/clj/one/sample/dev_server.clj
deleted file mode 100644
index 3190781..0000000
--- a/src/app/clj/one/sample/dev_server.clj
+++ /dev/null
@@ -1,98 +0,0 @@
-(ns one.sample.dev-server
- "Serve a friendly ClojureScript environment with code reloading and
- the ClojureScript application in both development and advanced
- compiled mode."
- (:use [ring.adapter.jetty :only (run-jetty)]
- [ring.middleware.file :only (wrap-file)]
- [ring.middleware.file-info :only (wrap-file-info)]
- [ring.middleware.params :only (wrap-params)]
- [ring.middleware.stacktrace :only (wrap-stacktrace)]
- [ring.util.response :only (file-response)]
- [compojure.core :only (defroutes GET POST ANY)]
- [cljs.repl :only (repl)]
- [cljs.repl.browser :only (repl-env)]
- [one.templates :only (load-html apply-templates render)]
- [one.host-page :only (application-host)]
- [one.sample.api :only (remote-routes)]
- [one.sample.config])
- (:require [net.cgrand.enlive-html :as html]
- [one.reload :as reload])
- (:import java.io.File))
-
-(defn- environment [uri]
- (if (= uri "/development") :development :production))
-
-(defn- make-host-page [request]
- {:status 200
- :headers {"Content-Type" "text/html; charset=utf-8"}
- :body (application-host config (environment (:uri request)))})
-
-(defroutes app-routes
- remote-routes
- (GET "/development" request (make-host-page request))
- (GET "/production" request (make-host-page request) )
- (GET "/design*" {{file :*} :route-params}
- (when (.endsWith file ".html")
- (load-html (.substring file 1))))
- (ANY "*" request (file-response "404.html" {:root "public"})))
-
-(defn- js-encoding [handler]
- (fn [request]
- (let [{:keys [headers body] :as response} (handler request)]
- (if (and (= (get headers "Content-Type") "text/javascript")
- (= (type body) File))
- (assoc-in response [:headers "Content-Type"]
- "text/javascript; charset=utf-8")
- response))))
-
-(defn- rewrite-design-uris [handler]
- (fn [{:keys [uri] :as request}]
- (if (some true? (map #(.startsWith uri (str "/design/" %))
- ["css" "javascripts" "images" "js" "favicon.ico"]))
- (handler (assoc request :uri (.substring uri 7)))
- (handler request))))
-
-;; We need to use this instead of Enlive's html-snippet, because
-;; html-snippet throws away the doctype
-(defn- html-parse
- "Parse a string into a seq of Enlive nodes."
- [s]
- (html/html-resource (java.io.StringReader. s)))
-
-(defn- active-menu-transform
- "Accepts the selected menu (a keyword) and the response and returns
- an updated response body with the correct menu activated."
- [menu response]
- (assoc response
- :body (render (html/transform (html-parse (:body response))
- [:ul#navigation (keyword (str "li." (name menu)))]
- (html/add-class "active")))))
-
-(defn- set-active-menu
- "Middleware which will highlight the current active menu item."
- [handler]
- (fn [request]
- (let [response (handler request)
- uri (:uri request)]
- (cond (= uri "/") (active-menu-transform :home response)
- (and (.startsWith uri "/design") (.endsWith uri ".html")) (active-menu-transform :design response)
- (= uri "/development") (active-menu-transform :development response)
- (= uri "/production") (active-menu-transform :production response)
- :else response))))
-
-(def ^:private app (-> app-routes
- (reload/watch-cljs config)
- (wrap-file "public")
- rewrite-design-uris
- wrap-file-info
- apply-templates
- js-encoding
- wrap-params
- set-active-menu
- wrap-stacktrace
- (reload/reload-clj (:reload-clj config))))
-
-(defn run-server
- "Start the development server on port 8080."
- []
- (run-jetty (var app) {:join? false :port 8080}))
diff --git a/src/app/clj/one/sample/prod_server.clj b/src/app/clj/one/sample/prod_server.clj
deleted file mode 100644
index 3526b61..0000000
--- a/src/app/clj/one/sample/prod_server.clj
+++ /dev/null
@@ -1,29 +0,0 @@
-(ns one.sample.prod-server
- "Production server serves the backend API. This is only required if
- there is a backend API."
- (:use [ring.adapter.jetty :only (run-jetty)]
- [ring.middleware.file :only (wrap-file)]
- [ring.middleware.file-info :only (wrap-file-info)]
- [ring.middleware.params :only (wrap-params)]
- [ring.util.response :only (file-response)]
- [compojure.core :only (defroutes ANY)]
- [one.sample.api :only (remote-routes)]))
-
-(def ^:private root "out/public")
-
-;; HACK: Something about the defroutes below requires that the
-;; out/public directory exist, or we get a compile error.
-(.mkdirs (java.io.File. "out/public"))
-
-(defroutes app-routes
- remote-routes
- (-> (ANY "*" request (file-response "404.html" {:root root}))
- (wrap-file root)
- wrap-file-info))
-
-(def ^:private app (-> app-routes
- wrap-params))
-
-(defn run-server []
- (let [port (Integer/parseInt (get (System/getenv) "PORT" "8080"))]
- (run-jetty (var app) {:join? false :port port})))
diff --git a/src/app/clj/one/sample/repl.clj b/src/app/clj/one/sample/repl.clj
deleted file mode 100644
index 0eb9d2b..0000000
--- a/src/app/clj/one/sample/repl.clj
+++ /dev/null
@@ -1,36 +0,0 @@
-(ns one.sample.repl
- "The starting namespace for the project. This is the namespace that
- users will land in when they start a Clojure REPL. It exists to
- provide convenience functions like 'go' and 'dev-server'."
- (:use [clojure.repl])
- (:require [one.tools :as tools]
- [one.sample.dev-server :as dev]
- [clojure.java.browse :as browse]))
-
-(defn go
- "Start a browser-connected REPL and launch a browser to talk to it."
- []
- (dev/run-server)
- (future (Thread/sleep 3000)
- (browse/browse-url "http://localhost:8080/development"))
- (tools/cljs-repl))
-
-(defn dev-server
- "Start the development server and open the host application in the
- default browser."
- []
- (dev/run-server)
- (future (Thread/sleep 3000)
- (browse/browse-url "http://localhost:8080")))
-
-;; This is a convenience function so that people can start a CLJS REPL
-;; without having to type in (tools/cljs-repl)
-(defn cljs-repl
- "Start a ClojureScript REPL."
- []
- (tools/cljs-repl))
-
-(println)
-(println "Type (go) to launch the development server and setup a browser-connected REPL.")
-(println "Type (dev-server) to launch only the development server.")
-(println)
diff --git a/src/app/cljs-macros/one/sample/snippets.clj b/src/app/cljs-macros/one/sample/snippets.clj
deleted file mode 100644
index 71c2e7c..0000000
--- a/src/app/cljs-macros/one/sample/snippets.clj
+++ /dev/null
@@ -1,15 +0,0 @@
-(ns one.sample.snippets
- "Macros for including HTML snippets in the ClojureScript application
- at compile time."
- (:use [one.templates :only (render)])
- (:require [net.cgrand.enlive-html :as html]))
-
-(defn- snippet [file id]
- (render (html/select (html/html-resource file) id)))
-
-(defmacro snippets
- "Expands to a map of HTML snippets which are extracted from the
- design templates."
- []
- {:form (snippet "form.html" [:div#form])
- :greeting (snippet "greeting.html" [:div#greeting])})
diff --git a/src/app/cljs/newapp/core.cljs b/src/app/cljs/newapp/core.cljs
new file mode 100644
index 0000000..5af6d18
--- /dev/null
+++ b/src/app/cljs/newapp/core.cljs
@@ -0,0 +1,32 @@
+(ns ^{:doc "Contains the entry point for the newapp application."}
+ newapp.core
+ (:require [goog.uri.utils :as uri]
+ [clojure.browser.repl :as repl]
+ [one.dispatch :as dispatch]))
+
+;; **TODO:** Add marginalia comment to explain what `:export` is for.
+
+(defn- server
+ "Return a string which is the scheme and domain portion of the URL
+ for the server from which this code was served."
+ []
+ (let [location (.toString window.location ())]
+ (str (uri/getScheme location) "://" (uri/getDomain location))))
+
+(defn ^:export repl
+ "Connects to a ClojureScript REPL running on localhost port 9000.
+
+ This allows a browser-connected REPL to send JavaScript to the
+ browser for evaluation. This function should be called from a script
+ in the development host HTML page."
+ []
+ (repl/connect (str (server) ":9000/repl")))
+
+(defn ^:export start
+ "Start the application by firing a `:init` event which will cause the
+ form view to be displayed.
+
+ This function must be called from the host HTML page to start the
+ application."
+ []
+ (js/alert "OK!"))
diff --git a/src/app/cljs/one/sample/animation.cljs b/src/app/cljs/one/sample/animation.cljs
deleted file mode 100644
index 9710e34..0000000
--- a/src/app/cljs/one/sample/animation.cljs
+++ /dev/null
@@ -1,139 +0,0 @@
-(ns ^{:doc "Defines animations which are used in the sample
- application."}
- one.sample.animation
- (:use [one.core :only (start)]
- [one.browser.animation :only (bind parallel serial play play-animation)]
- [domina :only (by-id set-html! set-styles! destroy-children! append! single-node)]
- [domina.xpath :only (xpath)])
- (:require [goog.dom.forms :as gforms]
- [goog.style :as style]))
-
-(def form "//div[@id='form']")
-(def cloud "//div[@id='greeting']")
-(def label "//label[@id='name-input-label']/span")
-
-(def ^:private
- form-in {:effect :fade :start 0 :end 1 :time 800})
-
-(defn initialize-views
- "Accepts the form and greeting view HTML and adds them to the
- page. Animates the form sliding in from above. This function must be
- run before any other view functions. It may be called from any state
- to reset the UI."
- [form-html greeting-html]
- (let [content (xpath "//div[@id='content']")]
- (destroy-children! content)
- (set-html! content form-html)
- (append! content greeting-html)
- ;; Required for IE8 to work correctly
- (style/setOpacity (single-node (xpath label)) 1)
- (set-styles! (xpath cloud) {:opacity "0" :display "none" :margin-top "-500px"})
- (set-styles! (by-id "greet-button") {:opacity "0.2" :disabled true})
- (play form form-in {:after #(.focus (by-id "name-input") ())})))
-
-(comment ;; Try it
-
- (initialize-views (:form one.sample.view/snippets)
- (:greeting one.sample.view/snippets))
-
- )
-
-(defn label-move-up
- "Move the passed input field label above the input field. Run when
- the field gets focus and is empty."
- [label]
- (play label [{:effect :color :end "#53607b" :time 200}
- {:effect :slide :up 40 :time 200}]))
-
-(defn label-fade-out
- "Make the passed input field label invisible. Run when the input
- field loses focus and contains a valid input value."
- [label]
- (play label {:effect :fade :end 0 :time 200}))
-
-(def move-down [{:effect :fade :end 1 :time 200}
- {:effect :color :end "#BBC4D7" :time 200}
- {:effect :slide :down 40 :time 200}])
-
-(def fade-in {:effect :fade :end 1 :time 400})
-
-(def fade-out {:effect :fade :end 0 :time 400})
-
-(defn label-move-down
- "Make the passed input field label visible and move it down into the
- input field. Run when an input field loses focus and is empty."
- [label]
- (play label move-down))
-
-(comment ;; Examples of label effects.
-
- (label-move-up label)
- (label-fade-out label)
- (label-move-down label)
- )
-
-(defn show-greeting
- "Move the form out of view and the greeting into view. Run when the
- submit button is clicked and the form has valid input."
- []
- (let [e {:effect :fade :end 0 :time 500}]
- (play-animation #(parallel (bind form e)
- (bind label e) ; Since the label won't fade in IE
- (bind cloud
- {:effect :color :time 500} ; Dummy animation for delay purposes
- {:effect :fade-in-and-show :time 600}))
- {:before #(gforms/setDisabled (by-id "name-input") true)
- ;; We need this next one because IE8 won't hide the button
- :after #(set-styles! (by-id "greet-button") {:display "none"})})))
-
-(defn show-form
- "Move the greeting cloud out of view and show the form. Run when the
- back button is clicked from the greeting view."
- []
- (play-animation (serial (parallel (bind cloud {:effect :fade-out-and-hide :time 500})
- (bind form
- {:effect :color :time 300} ; Dummy animation for delay purposes
- form-in)
- (bind label fade-in move-down)))
- {;; Because IE8 won't hide the button, we need to
- ;; toggle it between displaying inline and none
- :before #(set-styles! (by-id "greet-button") {:display "inline"})
- :after #(do
- (gforms/setDisabled (by-id "name-input") false)
- (.focus (by-id "name-input") ()))}))
-
-(comment ;; Switch between greeting and form views
-
- (label-move-up label)
- (show-greeting)
- (show-form)
- )
-
-(defn disable-button
- "Accepts an element id for a button and disables it. Fades the
- button to 0.2 opacity."
- [id]
- (let [button (by-id id)]
- (gforms/setDisabled button true)
- (play button {:effect :fade :end 0.2 :time 400})))
-
-(defn enable-button
- "Accepts an element id for a button and enables it. Fades the button
- to an opactiy of 1."
- [id]
- (let [button (by-id id)]
- (gforms/setDisabled button false)
- (play button fade-in)))
-
-(comment ;; Examples of all effects
-
- (initialize-views (:form one.sample.view/snippets)
- (:greeting one.sample.view/snippets))
- (label-move-up label)
- (label-fade-out label)
- (show-greeting)
- (show-form)
-
- (disable-button "greet-button")
- (enable-button "greet-button")
- )
diff --git a/src/app/cljs/one/sample/controller.cljs b/src/app/cljs/one/sample/controller.cljs
deleted file mode 100644
index df31549..0000000
--- a/src/app/cljs/one/sample/controller.cljs
+++ /dev/null
@@ -1,70 +0,0 @@
-(ns ^{:doc "Respond to user actions by updating local and remote
- application state."}
- one.sample.controller
- (:use [one.browser.remote :only (request)]
- [one.sample.model :only (state)])
- (:require [cljs.reader :as reader]
- [clojure.browser.event :as event]
- [one.dispatch :as dispatch]
- [goog.uri.utils :as uri]))
-
-(defmulti action
- "Accepts a map containing information about an action to perform.
-
- Actions may cause state changes on the client or the server. This
- function dispatches on the value of the `:type` key and currently
- supports `:init`, `:form`, and `:greeting` actions.
-
- The `:init` action will initialize the appliation's state.
-
- The `:form` action will only update the status atom, setting its state
- to `:from`.
-
- The `:greeting` action will send the entered name to the server and
- update the state to `:greeting` while adding `:name` and `:exists`
- values to the application's state."
- :type)
-
-(defmethod action :init [_]
- (reset! state {:state :init}))
-
-(defmethod action :form [_]
- (when-not (#{:form :init} (:state @state))
- (swap! state assoc :state :form)))
-
-(defn host
- "Get the name of the host which served this script."
- []
- (uri/getHost (.toString window.location ())))
-
-(defn remote
- "Accepts a function id (an identifier for this request), data (the
- data to send to the server) and a callback function which will be
- called if the transmission is successful. Perform an Ajax `POST`
- request to the backend API which sends the passed data to the
- server.
-
- A tranmission error will add an error message to the application's
- state."
- [f data on-success]
- (request f (str (host) "/remote")
- :method "POST"
- :on-success #(on-success (reader/read-string (:body %)))
- :on-error #(swap! state assoc :error "Error communicating with server.")
- :content (str "data=" (pr-str {:fn f :args data}))))
-
-(defn add-name-callback
- "This is the success callback function which will be called when a
- request is successful. Accepts a name and a map of response data.
- Sets the current state to `:greeting` and adds the `:name` and
- `:exists` values to the application's state."
- [name response]
- (swap! state (fn [old]
- (assoc (assoc old :state :greeting :name name)
- :exists (boolean (:exists response))))))
-
-(defmethod action :greeting [{name :name}]
- (remote :add-name {:name name} #(add-name-callback name %)))
-
-(dispatch/react-to #{:init :form :greeting}
- (fn [t d] (action (assoc d :type t))))
diff --git a/src/app/cljs/one/sample/core.cljs b/src/app/cljs/one/sample/core.cljs
deleted file mode 100644
index 50c4b57..0000000
--- a/src/app/cljs/one/sample/core.cljs
+++ /dev/null
@@ -1,33 +0,0 @@
-(ns ^{:doc "Contains the entry point for the ClojureScript sample application."}
- one.sample.core
- (:require [goog.uri.utils :as uri]
- [clojure.browser.repl :as repl]
- [one.dispatch :as dispatch]
- [one.sample.view :as view]))
-
-;; **TODO:** Add marginalia comment to explain what `:export` is for.
-
-(defn- server
- "Return a string which is the scheme and domain portion of the URL
- for the server from which this code was served."
- []
- (let [location (.toString window.location ())]
- (str (uri/getScheme location) "://" (uri/getDomain location))))
-
-(defn ^:export repl
- "Connects to a ClojureScript REPL running on localhost port 9000.
-
- This allows a browser-connected REPL to send JavaScript to the
- browser for evaluation. This function should be called from a script
- in the development host HTML page."
- []
- (repl/connect (str (server) ":9000/repl")))
-
-(defn ^:export start
- "Start the application by firing a `:init` event which will cause the
- form view to be displayed.
-
- This function must be called from the host HTML page to start the
- application."
- []
- (dispatch/fire :init))
diff --git a/src/app/cljs/one/sample/history.cljs b/src/app/cljs/one/sample/history.cljs
deleted file mode 100644
index d966f51..0000000
--- a/src/app/cljs/one/sample/history.cljs
+++ /dev/null
@@ -1,23 +0,0 @@
-(ns ^{:doc "When this library is loaded, a listener function is added
- which will be run when a :form or :greeting event is fired. This
- allows the use of the back button to navigate between views. This is
- accomplished by using library.browser.history to keep track of views
- that have previously been visited, and traversing them when
- navigation events are detected."}
- one.sample.history
- (:require [one.dispatch :as dispatch]
- [one.browser.history :as history]))
-
-(defn nav-handler
- "Handle navigation events by firing the appropriate view token."
- [{:keys [token navigation?]}]
- (when navigation?
- (dispatch/fire token)))
-
-(def ^{:doc "The global history object for this application."}
- history (history/history nav-handler))
-
-(dispatch/react-to #{:init :form :greeting}
- (fn [t _]
- (history/set-token history (if (#{:init} t) :form t))))
-
diff --git a/src/app/cljs/one/sample/logging.cljs b/src/app/cljs/one/sample/logging.cljs
deleted file mode 100644
index f680e03..0000000
--- a/src/app/cljs/one/sample/logging.cljs
+++ /dev/null
@@ -1,26 +0,0 @@
-(ns ^{:doc "When this library is loaded, create a logger named
-'events' and send all application-specific events to it.
-
-To view log messages in the browser console, add a call
-to `(log/console-output)` to this namespace or evaluate this from the
-REPL.
-
-For more information see library.logging."}
- one.sample.logging
- (:require [one.dispatch :as dispatch]
- [one.logging :as log]))
-
-(def ^{:doc "The logger that receives all application-specific events."}
- logger (log/get-logger "events"))
-
-(dispatch/react-to (constantly true)
- (fn [t d] (log/info logger (str (pr-str t) " - " (pr-str d)))))
-
-(comment
- ;; log to the console
- (log/start-display (log/console-output))
- ;; log to to the "fancy" window
- (log/start-display (log/fancy-output "main"))
- ;; change the logging level
- (log/set-level logger :fine)
- )
diff --git a/src/app/cljs/one/sample/model.cljs b/src/app/cljs/one/sample/model.cljs
deleted file mode 100644
index b3524cb..0000000
--- a/src/app/cljs/one/sample/model.cljs
+++ /dev/null
@@ -1,152 +0,0 @@
-(ns ^{:doc "Contains client-side state, validators for input fields
- and functions which react to changes made to the input fields."}
- one.sample.model
- (:require [one.dispatch :as dispatch]))
-
-(def ^{:doc "An atom containing a map which is the application's current state."}
- state (atom {}))
-
-(add-watch state :state-change-key
- (fn [k r o n]
- (dispatch/fire :state-change n)))
-
-(def ^{:private true
- :doc "An atom containing the state of the greeting form and
- each of its fields."}
- greeting-form (atom {}))
-
-(add-watch greeting-form :form-change-key
- (fn [k r o n]
- (dispatch/fire :form-change {:old o :new n})))
-
-(defmulti ^:private new-status
- (fn [& args] (vec args)))
-
-(def error-status
- {:status :error
- :error "Are you sure about that? Names must have at least two characters."})
-
-(def editing-error-status
- {:status :editing-error
- :error "Names must have at least two characters."})
-
-(defmethod new-status [:empty :focus :empty] [p e f]
- {:status :editing})
-
-(defmethod new-status [:editing :finished :empty] [p e f]
- {:status :empty})
-
-(defmethod new-status [:editing :change :empty] [p e f]
- {:status :editing})
-
-(defmethod new-status [:editing :change :error] [p e f]
- {:status :editing})
-
-(defmethod new-status [:editing :change :valid] [p e f]
- {:status :editing-valid})
-
-(defmethod new-status [:editing :finished :error] [p e f]
- error-status)
-
-(defmethod new-status [:editing-valid :change :error] [p e f]
- {:status :editing})
-
-(defmethod new-status [:editing-valid :change :valid] [p e f]
- {:status :editing-valid})
-
-(defmethod new-status [:editing-valid :finished :valid] [p e f]
- {:status :valid})
-
-(defmethod new-status [:error :focus :error] [p e f]
- editing-error-status)
-
-(defmethod new-status [:editing-error :change :error] [p e f]
- editing-error-status)
-
-(defmethod new-status [:editing-error :finished :error] [p e f]
- error-status)
-
-(defmethod new-status [:editing-error :change :valid] [p e f]
- {:status :editing-valid})
-
-(defmethod new-status [:editing-error :change :empty] [p e f]
- {:status :editing-error})
-
-(defmethod new-status [:editing-error :finished :empty] [p e f]
- {:status :empty})
-
-(defmethod new-status [:valid :focus :valid] [p e f]
- {:status :editing-valid})
-
-(defmethod new-status [:valid :finished :empty] [p e f]
- {:status :empty})
-
-(defmethod new-status :default [p e f]
- {:status p})
-
-(defmulti ^:private validate
- "Accepts a form id and a value and returns a map
- with `:value`, `:status`, and `:error` keys. Status will be set to
- either `:valid` or `:error`. If there was an error, then there will be
- an error message associated with the `:error` key."
- (fn [id _] id))
-
-(defmethod validate "name-input" [_ v]
- (cond (= (count v) 0) :empty
- (= (count v) 1) :error
- :else :valid))
-
-(defn- form-status
- "Calculates the status of the whole form based on the status of each
- field. Retuns `:finished` or `:editing`."
- [m]
- (if (every? #(or (= % :valid) (= % :editing-valid)) (map :status (vals (:fields m))))
- :finished
- :editing))
-
-(defn- set-field-value
- "Accepts a field-id and value. Validates the field and updates the
- greeting form atom."
- [field-id type value]
- (swap! greeting-form
- (fn [old]
- (let [field (get (:fields old) field-id {})
- field-status (assoc (new-status (-> old :fields field-id :status)
- type
- (validate field-id value))
- :value value)
- new (assoc-in old [:fields field-id] field-status)]
- (assoc new :status (form-status new))))))
-
-(defn- set-editing
- "Update the form state for a given field to indicate that the form
- is still being edited."
- [id]
- (swap! greeting-form
- (fn [old]
- (let [field-map (-> old :fields id)
- status (or (:status field-map) :empty)
- field-status (new-status status
- :focus
- status)]
- (-> old
- (assoc-in [:fields id] (assoc field-status :value (:value field-map)))
- (assoc :status (form-status old)))))))
-
-(dispatch/react-to (fn [e] (= (first e) :field-finished))
- (fn [[_ id] value]
- (set-field-value id :finished value)))
-
-(dispatch/react-to (fn [e] (= (first e) :field-changed))
- (fn [[_ id] value]
- (set-field-value id :change value)))
-
-(dispatch/react-to (fn [e] (= (first e) :editing-field))
- (fn [[_ id] _]
- (set-editing id)))
-
-(dispatch/react-to #{:form-submit}
- (fn [t d]
- (let [form-data @greeting-form]
- (when (= (:status form-data) :finished)
- (dispatch/fire :greeting {:name (-> form-data :fields "name-input" :value)})))))
diff --git a/src/app/cljs/one/sample/view.cljs b/src/app/cljs/one/sample/view.cljs
deleted file mode 100644
index 25f3c8d..0000000
--- a/src/app/cljs/one/sample/view.cljs
+++ /dev/null
@@ -1,150 +0,0 @@
-(ns ^{:doc "Render the views for the application."}
- one.sample.view
- (:use [domina :only (set-html! set-styles! styles by-id set-style!
- by-class value set-value! set-text! nodes single-node)]
- [domina.xpath :only (xpath)]
- [one.browser.animation :only (play)])
- (:require-macros [one.sample.snippets :as snippets])
- (:require [goog.events.KeyCodes :as key-codes]
- [goog.events.KeyHandler :as key-handler]
- [clojure.browser.event :as event]
- [one.dispatch :as dispatch]
- [one.sample.animation :as fx]))
-
-(def ^{:doc "A map which contains chunks of HTML which may be used
- when rendering views."}
- snippets (snippets/snippets))
-
-(defmulti render-button
- "Render the submit button based on the current state of the
- form. The button is disabled while the user is editing the form and
- becomes enabled when the form is complete."
- identity)
-
-(defmethod render-button :default [_])
-
-(defmethod render-button [:finished :editing] [_]
- (fx/disable-button "greet-button"))
-
-(defmethod render-button [:editing :finished] [_]
- (fx/enable-button "greet-button"))
-
-(defmulti render-form-field
- "Render a form field based on the current state transition. Form
- fields are validated as soon as they lose focus. There are six
- transitions and each one has its own animation."
- :transition)
-
-(defmethod render-form-field :default [_])
-
-(defn- label-xpath
- "Accepts an element id for an input field and return the xpath
- string to the label for that field."
- [id]
- (str "//label[@id='" id "-label']/span"))
-
-(defmethod render-form-field [:empty :editing] [{:keys [id]}]
- (fx/label-move-up (label-xpath id)))
-
-(defmethod render-form-field [:editing :empty] [{:keys [id]}]
- (fx/label-move-down (label-xpath id)))
-
-(defmethod render-form-field [:editing-valid :valid] [{:keys [id]}]
- (fx/label-fade-out (label-xpath id)))
-
-(defmethod render-form-field [:valid :editing-valid] [{:keys [id]}]
- (play (label-xpath id) fx/fade-in))
-
-(defmethod render-form-field [:editing :error] [{:keys [id error]}]
- (let [error-element (by-id (str id "-error"))]
- (set-style! error-element "opacity" "0")
- (set-html! error-element error)
- (play error-element fx/fade-in)))
-
-(defn- swap-error-messages
- "Accepts an id and an error message and fades the old error message
- out and the new one in."
- [id error]
- (let [error-element (by-id (str id "-error"))]
- (play error-element fx/fade-out
- {:name "fade out error"})
- (play error-element fx/fade-in {:before #(set-html! error-element error)})))
-
-(defmethod render-form-field [:error :editing-error] [{:keys [id error]}]
- (swap-error-messages id error))
-
-(defmethod render-form-field [:editing-error :error] [{:keys [id error]}]
- (swap-error-messages id error))
-
-(defmethod render-form-field [:editing-error :editing-valid] [{:keys [id]}]
- (let [error-element (by-id (str id "-error"))]
- (play error-element (assoc fx/fade-out :time 200))))
-
-(defmethod render-form-field [:editing-error :empty] [{:keys [id]}]
- (let [error-element (by-id (str id "-error"))]
- (play error-element (assoc fx/fade-out :time 200))
- (fx/label-move-down (label-xpath id))))
-
-(defn- add-input-event-listeners
- "Accepts a field-id and creates listeners for blur and focus events which will then fire
- `:field-changed` and `:editing-field` events."
- [field-id]
- (let [field (by-id field-id)
- keyboard (goog.events.KeyHandler. (by-id "form"))]
- (event/listen field
- "blur"
- #(dispatch/fire [:field-finished field-id] (value field)))
- (event/listen field
- "focus"
- #(dispatch/fire [:editing-field field-id]))
- (event/listen field
- "keyup"
- #(dispatch/fire [:field-changed field-id] (value field)))
- (event/listen keyboard
- "key"
- (fn [e] (when (= (.-keyCode e) key-codes/ENTER)
- (do (.blur (by-id "name-input") ())
- (dispatch/fire :form-submit)))))))
-
-(defmulti render
- "Accepts a map which represents the current state of the application
- and renders a view based on the value of the `:state` key."
- :state)
-
-(defmethod render :init [_]
- (fx/initialize-views (:form snippets) (:greeting snippets))
- (add-input-event-listeners "name-input")
- (event/listen (by-id "greet-button")
- "click"
- #(dispatch/fire :greeting
- {:name (value (by-id "name-input"))})))
-
-(defmethod render :form [{:keys [state error name]}]
- (fx/show-form)
- (set-value! (by-id "name-input") "")
- (dispatch/fire [:field-finished "name-input"] ""))
-
-(defmethod render :greeting [{:keys [state name exists]}]
- (set-text! (single-node (by-class "name")) name)
- (set-text! (single-node (by-class "again")) (if exists "again" ""))
- (fx/show-greeting))
-
-(dispatch/react-to #{:state-change} (fn [_ m] (render m)))
-
-(defn- form-fields-status
- "Given a map of old and new form states, generate a map with `:id`,
- `:transition` and `:error` keys which can be passed to
- `render-form-field`."
- [m]
- (map #(hash-map :id %
- :transition [(or (-> m :old :fields % :status) :empty)
- (-> m :new :fields % :status)]
- :error (-> m :new :fields % :error))
- (keys (-> m :new :fields))))
-
-(dispatch/react-to #{:form-change}
- (fn [_ m]
- (doseq [s (form-fields-status m)]
- (render-form-field s))
- (render-button [(-> m :old :status)
- (-> m :new :status)] )))
diff --git a/templates/application.html b/templates/application.html
index 30e744f..b2cc08a 100644
--- a/templates/application.html
+++ b/templates/application.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>ClojureScript One</title>
+ <title>newapp</title>
<meta name="description" content="">
<meta name="author" content="">
@@ -12,21 +12,7 @@
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
- <!-- Le styles -->
- <link href="favicon.ico" rel="shortcut icon" type="image/x-icon">
- <link href="css/one.css" rel="stylesheet">
- <!-- <link href="css/two.css" rel="stylesheet"> -->
- <style type="text/css">
- body {
- padding-top: 60px;
- }
- </style>
-
- <!-- Le fav and touch icons -->
- <link rel="shortcut icon" href="images/favicon.ico">
- <link rel="apple-touch-icon" href="images/apple-touch-icon.png">
- <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
- <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
+ <link href="css/bootstrap.css" rel="stylesheet">
<!-- Add xpath support to IE. Domina needs this -->
<!--[if IE]>
diff --git a/templates/form.html b/templates/form.html
deleted file mode 100644
index 05d88da..0000000
--- a/templates/form.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<_within file="application.html">
-
- <div id="content">
- <div id="form">
- <h1 id="header">My form</h1>
- <div class="input">
- <label id="name-input-label">
- <span>Enter your name</span>
- <input id="name-input" size="30" type="text"/>
- </label>
- <div id="name-input-error" class="small error">&nbsp;</div>
- </div>
- <input id="greet-button" class="button green" type="button" value="Done!">
- </div>
- </div>
-
-</_within>
diff --git a/templates/greeting.html b/templates/greeting.html
deleted file mode 100644
index b3943a8..0000000
--- a/templates/greeting.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<_within file="application.html">
-
- <div id="content">
- <div id="greeting">
- <h2>Hello</h2>
- <div class="break"></div>
- <h3><span class="again">again</span>&nbsp;<span class="name">Person</span></h3>
- </div>
- </div>
-
-</_within>
diff --git a/templates/toolbar.html b/templates/toolbar.html
index 82ea95c..2164340 100644
--- a/templates/toolbar.html
+++ b/templates/toolbar.html
@@ -1,12 +1,14 @@
<div class="topbar">
- <div class="container">
- <a class="brand" href="/">ClojureScript One</a>
+ <div class="topbar-inner">
+ <div class="container">
+ <a class="brand" href="/">newapp</a>
- <ul id="navigation" class="nav">
- <li class="home"><a href="/">Home</a></li>
- <li class="design"><a href="/design.html">Design</a></li>
- <li class="development"><a href="/development">Development</a></li>
- <li class="production"><a href="/production">Production</a></li>
- </ul>
+ <ul id="navigation" class="nav">
+ <li class="home"><a href="/">Home</a></li>
+ <li class="design"><a href="/design.html">Design</a></li>
+ <li class="development"><a href="/development">Development</a></li>
+ <li class="production"><a href="/production">Production</a></li>
+ </ul>
+ </div>
</div>
</div>
--
1.7.4.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment