Created
December 26, 2013 13:47
-
-
Save minikomi/8134035 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns chanplay.core | |
(:require | |
[goog.dom :as dom] | |
[goog.events :as events] | |
[cljs.core.async :as async | |
:refer [<! >! chan close! sliding-buffer put! alts!]] | |
[jayq.core | |
:refer [$ append ajax inner html $deferred when done resolve pipe on] :as jq] | |
[crate.core :as crate] | |
) | |
(:require-macros | |
[cljs.core.async.macros :as m :refer [go alt!]] | |
)) | |
(enable-console-print!) | |
;; Channel helpers | |
(defn data-from-event [event] | |
(-> event .-currentTarget $ .data (js->clj :keywordize-keys true))) | |
(defn fields-value-map [form-selector fields] | |
(into {} (map | |
(fn [fld] | |
[fld (jq/val ($ (str form-selector " input[name=" (name fld) "]")))] ) | |
fields))) | |
(defn form-submit-chan [form-selector msg-name fields] | |
(let [rc (chan)] | |
(on ($ "body") :submit form-selector {} | |
(fn [e] | |
(jq/prevent e) | |
(put! rc [msg-name (fields-value-map form-selector fields)]))) | |
rc)) | |
(defn click-chan [selector msg-name] | |
(let [rc (chan)] | |
(on ($ "body") :click selector {} | |
(fn [e] | |
(jq/prevent e) | |
(put! rc [msg-name (data-from-event e)]))) | |
rc)) | |
;; ----------- Templates | |
(defn modal-form [{:keys [mode] :as state}] | |
(when (= mode :modal) | |
[:div.modal | |
[:h4 "Add Task"] | |
[:form.new-task-form | |
[:input.new-task-name {:type "text" | |
:name "content" | |
:placeholder "New Task"}] | |
[:p | |
[:input {:type "submit" :value "Save" :class "btn btn-primary"}] | |
[:a {:href "#" :class " cancel btn"} "cancel"]]]])) | |
(defn todo-task [idx {:keys [completed] :as task}] | |
(let [control (if completed | |
[:i {:class "icon-ok-sign icon-white"} "●"] | |
[:a {:href "#" :class "check" :data-task-index idx} | |
[:i {:class "icon-ok-circle icon-white"} "○"]])] | |
[:li | |
control | |
[:span {:class (if completed "completed")} | |
(:content task)]] | |
)) | |
(defn todo-list [{:keys [todos] :as state}] | |
[:div | |
[:p | |
[:a {:href "#" :class "new-todo btn btn-primary"} "Add task"]] | |
[:ul {:class "todo-list unstyled"} | |
(map-indexed todo-task todos)] | |
(modal-form state)]) | |
;; ----------- Handlers | |
(defn handle [state event] | |
(let [mode (:mode state) | |
event-type (first event) | |
event-data (second event)] | |
(mode | |
{:list | |
(case event-type | |
; change mode to :modal | |
:add-todo (assoc state :mode :modal) | |
; change completed status | |
:complete-todo (assoc-in state [:todos (:taskIndex event-data) :completed] true) | |
; default | |
state) | |
:modal | |
(case event-type | |
; change mode to :list | |
:cancel-modal (assoc state :mode :list) | |
; create new task | |
:create-todo (-> state | |
(assoc :mode :list) | |
(assoc :todos | |
(conj (:todos state) | |
{:content (:content event-data) :completed false}))) | |
; default | |
state) | |
}))) | |
;; ---------- App loop | |
(def initial-state {:mode :list | |
:todos [{:content "Buy a new car" | |
:completed false}]}) | |
(let [add-todo (click-chan "a.new-todo" :add-todo) | |
complete-todo (click-chan ".todo-list a.check" :complete-todo) | |
cancel-modal (click-chan ".modal a.cancel" :cancel-modal) | |
create-todo (form-submit-chan ".modal form" :create-todo [:content])] | |
(go | |
(loop [state initial-state] | |
(println state) | |
; display | |
(jq/html ($ "#content") (crate/html (todo-list state))) | |
; handle & recur | |
(let [event (first (alts! [add-todo complete-todo cancel-modal create-todo]))] | |
(println event) | |
(recur (handle state event)))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment