Created
November 15, 2012 12:31
-
-
Save drcode/4078420 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 webfui-examples.add-two-numbers-low-level.core | |
| (:use [webfui.dom :only [defdom add-dom-watch]] | |
| [webfui.state-patches :only [patch]])) | |
| (def my-dom (atom nil)) | |
| (defdom my-dom) | |
| (def a 0) | |
| (def b 0) | |
| (defn render-all [old-dom] | |
| [:div [:input {:type :text :watch :a-watch :value a}] | |
| " plus " | |
| [:input {:type :text :watch :b-watch :value b}] | |
| [:p " equals "] | |
| [:span (+ a b)]]) | |
| (defn update-dom [] | |
| (swap! my-dom render-all)) | |
| (update-dom) | |
| (defn valid-integer [s] | |
| (and (< (count s) 15) (re-matches #"^[0-9]+$" s))) | |
| (add-dom-watch :a-watch | |
| (fn [old-element new-element] | |
| (let [new-a (get-in new-element [1 :value])] | |
| (when (valid-integer new-a) | |
| (def a (js/parseInt new-a)))) | |
| (update-dom))) | |
| (add-dom-watch :b-watch | |
| (fn [old-element new-element] | |
| (let [new-b (get-in new-element [1 :value])] | |
| (when (valid-integer new-b) | |
| (def b (js/parseInt new-b)))) | |
| (update-dom))) | |
| (ns webfui-examples.add-two-numbers.core | |
| (:use [webfui.framework :only [launch-app]]) | |
| (:use-macros [webfui.framework.macros :only [add-dom-watch]])) | |
| (defn render-all [state] | |
| (let [{:keys [a b]} state] | |
| [:div [:input#a {:watch :watch :value a}] | |
| " plus " | |
| [:input#b {:watch :watch :value b}] | |
| [:p " equals "] | |
| [:span (+ a b)]])) | |
| (defn valid-integer [s] | |
| (and (< (count s) 15) (re-matches #"^[0-9]+$" s))) | |
| (add-dom-watch :watch [state new-element] | |
| (let [{:keys [value id]} (second new-element)] | |
| (when (valid-integer value) | |
| {id (js/parseInt value)}))) | |
| (launch-app (atom {:a 0 :b 0}) render-all) | |
| (add-dom-watch :container [state new-element] | |
| {:position (get-attribute new-element :scroll-top)}) | |
| (add-dom-watch :text-field [state new-element] | |
| {:position (try-parse (get-attribute new-element :value))}) | |
| (add-mouse-watch :mouse [state first-element last-element points] | |
| (let [sizes (state :sizes) | |
| [from-index to-index] (map (comp :data second) [first-element last-element]) | |
| to-index (and (not= from-index to-index) to-index)] | |
| {:dragged-item (when (get-attribute first-element :active) | |
| {:point (last points) | |
| :from from-index | |
| :to to-index}) | |
| :sizes (if to-index | |
| (update-in sizes [to-index] + (sizes from-index)) | |
| sizes)})) | |
| (ns webfui-examples.calculator.core | |
| (:use [webfui.framework :only [launch-app]] | |
| [webfui.utilities :only [get-attribute clicked]]) | |
| (:use-macros [webfui.framework.macros :only [add-mouse-watch]])) | |
| (def initial-state {:amount nil | |
| :amount-decimal nil | |
| :accumulator 0 | |
| :operation nil | |
| :memory 0}) | |
| (def calculator-keys [[[:ac "AC" :ac] [:ms "MS" :ms] [:mr "MR" :mr] [:div "÷" :op]] | |
| [[:7 "7" :num] [:8 "8" :num] [:9 "9" :num] [:mult "×" :op]] | |
| [[:4 "4" :num] [:5 "5" :num] [:6 "6" :num] [:minus "-" :op]] | |
| [[:1 "1" :num] [:2 "2" :num] [:3 "3" :num] [:plus "+" :op]] | |
| [[:period "." :period] [:0 "0" :num] [:eq "=" :op]]]) | |
| (def operations {:div / | |
| :mult * | |
| :minus - | |
| :plus + | |
| :eq identity}) | |
| (defn right-shorten [s] | |
| (subs s 0 (dec (count s)))) | |
| (defn format-accumulator [accumulator] | |
| (loop [s (.toFixed accumulator 12)] | |
| (case (last s) | |
| \0 (recur (right-shorten s)) | |
| \. (right-shorten s) | |
| s))) | |
| (defn check-overflow [s] | |
| (cond (and (<= (count s) 12) (not= (last s) \.)) s | |
| (some (partial = \.) s) (recur (right-shorten s)) | |
| :else "OVERFLOW")) | |
| (defn render-display [{:keys [amount amount-decimal accumulator]}] | |
| (check-overflow (cond (not amount) (format-accumulator accumulator) | |
| amount-decimal (.toFixed amount amount-decimal) | |
| :else (str amount)))) | |
| (defn render-all [state] | |
| [:table [:tbody [:tr [:td {:colspan 4} | |
| [:div#display (render-display state)]]] | |
| (for [row calculator-keys] | |
| [:tr (for [[sym label mouse] row] | |
| [:td {:colspan ({:eq 2} sym 1)} | |
| [:div {:id sym | |
| :mouse mouse} | |
| label]])])]]) | |
| (add-mouse-watch :num [state first-element last-element] | |
| (when (clicked first-element last-element) | |
| (let [{:keys [amount amount-decimal]} state | |
| digit (js/parseInt (name (get-attribute first-element :id)))] | |
| (if amount-decimal | |
| {:amount (+ amount (/ digit 10 (apply * (repeat amount-decimal 10)))) | |
| :amount-decimal (inc amount-decimal)} | |
| {:amount (+ (* amount 10) digit)})))) | |
| (add-mouse-watch :op [state first-element last-element] | |
| (when (clicked first-element last-element) | |
| (let [{:keys [amount operation accumulator]} state] | |
| {:amount nil | |
| :amount-decimal nil | |
| :accumulator (if (and amount operation) | |
| ((operations operation) accumulator amount) | |
| (or amount accumulator)) | |
| :operation (get-attribute first-element :id)}))) | |
| (add-mouse-watch :period [state first-element last-element] | |
| (when (clicked first-element last-element) | |
| (when-not (:amount-decimal state) | |
| {:amount-decimal 0}))) | |
| (add-mouse-watch :ac [state first-element last-element] | |
| (when (clicked first-element last-element) | |
| (assoc initial-state :memory (:memory state)))) | |
| (add-mouse-watch :ms [state first-element last-element] | |
| (when (clicked first-element last-element) | |
| (let [{:keys [amount accumulator]} state] | |
| {:memory (or amount accumulator)}))) | |
| (add-mouse-watch :mr [state first-element last-element] | |
| (when (clicked first-element last-element) | |
| (let [{:keys [memory]} state] | |
| {:amount memory}))) | |
| (launch-app (atom initial-state) render-all) | |
| (def initial-state {:amount nil | |
| :amount-decimal nil | |
| :accumulator 0 | |
| :operation nil | |
| :memory :unknown}) | |
| (def my-state (atom initial-state)) | |
| (defn send [safe-state method uri fun] | |
| (xhr/send uri | |
| (fn [event] | |
| (let [response (.-target event)] | |
| (if (.isSuccess response) | |
| (fun (.getResponseText response)) | |
| (reset! my-state safe-state)))) | |
| (name method))) | |
| (defn memory-loaded [text] | |
| (let [memory (read-string text)] | |
| (swap! my-state assoc :memory memory :amount memory))) | |
| (defn memory-saved [] | |
| (swap! my-state assoc :memory :unknown)) | |
| (add-watch my-state :my-watch | |
| (fn [_ _ old new] | |
| (let [{:keys [amount memory]} new] | |
| (when (= amount :unknown) | |
| (if (= (:amount old) :unknown) | |
| (reset! my-state old) | |
| (send old :get "memory" memory-loaded))) | |
| (when (not= memory :unknown) | |
| (if (not= (:memory old) :unknown) | |
| (reset! my-state old) | |
| (send old :put (str "memory/" memory) memory-saved)))))) | |
| (launch-app my-state render-all) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I like this. This is nice.