Skip to content

Instantly share code, notes, and snippets.

@drcode
Created November 15, 2012 12:31
Show Gist options
  • Select an option

  • Save drcode/4078420 to your computer and use it in GitHub Desktop.

Select an option

Save drcode/4078420 to your computer and use it in GitHub Desktop.
(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)
@brycec
Copy link

brycec commented Nov 15, 2012

I like this. This is nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment