Created
April 1, 2016 20:07
-
-
Save andreloureiro/464e7221a309ebf77cfd37e4f2f5ae9f 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 nix.example | |
(:require [nix.core :refer [Observable run]] | |
[nix.dom :refer [make-dom-driver]])) | |
;; Checkbox Example | |
(defn CheckboxToggle [{:keys [DOM]}] | |
(let [{:keys [select]} DOM | |
checkbox-evs$ (:events (select "#cbox")) | |
checkbox-change$ (-> (checkbox-evs$ "change") | |
(.map #(.. % -target -checked)) | |
(.startWith false))] | |
{:DOM (-> checkbox-change$ | |
(.map (fn [v] | |
[:div nil | |
[:input {:id "cbox" :type "checkbox"}] | |
[:p nil (if v "toggled" "not")]])))})) | |
;; Input update | |
(defn InputUpdate [{:keys [DOM]}] | |
(let [{:keys [select]} DOM | |
input-evs$ (:events (select "#inputName")) | |
input-value$ (-> (input-evs$ "input") | |
(.map #(.. % -target -value)) | |
(.startWith ""))] | |
{:DOM (-> input-value$ | |
(.map (fn [v] [:div nil | |
[:input {:id "inputName" :type "text"}] | |
[:p nil (str "your name: " v)]])))})) | |
;; Counter | |
(defn render-vtree$ [state$] | |
(-> state$ | |
(.scan (fn [state action] (action state))) | |
(.map (fn [v] | |
[:div nil | |
[:button {:id "increment"} "increment"] | |
[:button {:id "decrement"} "decrement"] | |
[:p nil (str v)]])))) | |
(defn Counter [{:keys [DOM]}] | |
(let [{:keys [select]} DOM | |
btn-inc-evs$ (:events (select "#increment")) | |
increment$ (-> (btn-inc-evs$ "click") | |
(.map #(fn [c] (inc c)))) | |
btn-dec-evs$ (:events (select "#decrement")) | |
decrement$ (-> (btn-dec-evs$ "click") | |
(.map #(fn [c] (dec c)))) | |
state$ (-> Observable | |
(.merge increment$ decrement$) | |
(.startWith 0))] | |
{:DOM (render-vtree$ state$)})) | |
;; BMI | |
(defn LabeledSlider [{:keys [DOM props$]}] | |
(let [{:keys [select]} DOM | |
slider-evs$ (:events (select "#slider")) | |
slider-value$ (-> (slider-evs$ "input") | |
(.map #(.. % -target -value)) | |
(.startWith 10))] | |
{:DOM (-> Observable | |
(.combineLatest | |
props$ | |
slider-value$ | |
(fn [{:keys [label]} slider-value] | |
[:div nil | |
[:p nil (str label ": " slider-value " cm")] | |
[:input {:id "slider" | |
:type "range" | |
:min 0 | |
:max 100 | |
:value slider-value}]]))) | |
:value$ slider-value$})) | |
(defn BMI [{:keys [DOM]}] | |
(let [{:keys [select]} DOM | |
height-component (LabeledSlider {:DOM DOM | |
:props$ (-> Observable | |
(.of {:label "Height"}))} ) | |
weight-component (LabeledSlider {:DOM DOM | |
:props$ (-> Observable | |
(.of {:label "Weight"}))}) | |
state$ (-> Observable | |
(.combineLatest | |
(:value$ height-component) | |
(:value$ weight-component) | |
(fn [height weight] | |
(let [height-meters (* height 0.01) | |
bmi (/ weight (* height-meters height-meters))] | |
{:height height | |
:weight weight | |
:bmi bmi}))))] | |
{:DOM (-> state$ | |
(.combineLatest | |
(:DOM height-component) | |
(:DOM weight-component) | |
(fn [state height-dom weight-dom] | |
[:div nil | |
height-dom | |
weight-dom | |
[:strong nil (str "BMI is " (:bmi state))]]) | |
))})) | |
;; (defn BMI [{:keys [DOM]}] | |
;; (let [{:keys [select]} DOM | |
;; height$ (-> (select "#height" "input") | |
;; (.map #(.. % -target -value)) | |
;; (.startWith 170)) | |
;; weight$ (-> (select "#weight" "input") | |
;; (.map #(.. % -target -value)) | |
;; (.startWith 70)) | |
;; state$ (-> Observable | |
;; (.combineLatest | |
;; height$ | |
;; weight$ | |
;; (fn [height weight] | |
;; (let [height-meters (* height 0.01) | |
;; bmi (/ weight (* height-meters height-meters))] | |
;; {:height height | |
;; :weight weight | |
;; :bmi bmi}))))] | |
;; {:DOM (-> state$ | |
;; (.map (fn [state] | |
;; [:div nil | |
;; [:p nil (str "Height " (:height state) " cm")] | |
;; [:input {:id "height" :type "range" :min 140 :max 210 :value (:height state)}] | |
;; [:p nil (str "Weight " (:weight state) " kg")] | |
;; [:input {:id "weight" :type "range" :min 40 :max 140 :value (:weight state)}] | |
;; [:strong nil (str "BMI is " (:bmi state))]])))})) | |
;; Example container | |
(defn example-select-action$ [{:keys [select]} id v] | |
(let [btn-evs$ (:events (select id))] | |
(-> (btn-evs$ "click") | |
(.map (fn [_] v))))) | |
(defn Examples [{:keys [DOM]}] | |
(let [select-counter$ (example-select-action$ DOM "#one" 0) | |
select-checkbox$ (example-select-action$ DOM "#two" 1) | |
select-bmi$ (example-select-action$ DOM "#three" 2) | |
select-input-update$ (example-select-action$ DOM "#four" 3) | |
active-view$ (-> Observable | |
(.merge select-counter$ select-checkbox$ select-bmi$ select-input-update$) | |
(.startWith 2)) | |
{counter-dom$ :DOM} (Counter {:DOM DOM}) | |
{checkbox-toggle-dom$ :DOM} (CheckboxToggle {:DOM DOM}) | |
{bmi-dom$ :DOM} (BMI {:DOM DOM}) | |
{input-update-dom$ :DOM} (InputUpdate {:DOM DOM})] | |
{:DOM (-> active-view$ | |
(.combineLatest | |
counter-dom$ | |
checkbox-toggle-dom$ | |
bmi-dom$ | |
input-update-dom$ | |
(fn [active-view | |
counter-dom | |
checkbox-toggle-dom | |
bmi-dom | |
input-update-dom] | |
[:div nil | |
[:h1 nil "Nix Examples"] | |
[:button {:id "one"} "counter"] | |
[:button {:id "two"} "checkbox toggle"] | |
[:button {:id "three"} "bmi"] | |
[:button {:id "four"} "input update"] | |
[:hr] | |
(condp = active-view | |
0 counter-dom | |
1 checkbox-toggle-dom | |
2 bmi-dom | |
3 input-update-dom | |
[:div nil "Select an example"]) | |
])))})) | |
(defn input-value$ [{:keys [select]}] | |
(let [input-evs$ (:events (select "#input"))] | |
(-> (input-evs$ "input") | |
(.map #(.. % -target -value)) | |
(.startWith "")))) | |
(def drivers {:DOM (make-dom-driver "#app")}) | |
(run Examples drivers) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment