Last active
March 6, 2016 16:37
-
-
Save namelos/725a4e82f7c0f3a7ea64 to your computer and use it in GitHub Desktop.
cycle bmi calculator example
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
import { Observable } from 'rx' | |
import { run } from '@cycle/core' | |
import { makeDOMDriver, hJSX } from '@cycle/dom' | |
import { makeHTTPDriver } from '@cycle/http' | |
const { of, just, combineLatest } = Observable | |
const square = x => x * x | |
const bmi = (weight, height) => | |
Math.round(weight / square(height * 0.01)) | |
const renderWeight = weight => <div> | |
weight { weight } kg | |
<input type="range" id="weight" min="40" max="140" value={ weight } /> | |
</div> | |
const renderHeight = height => <div> | |
height { height } kg | |
<input type="range" id="height" min="140" max="210" value={ height } /> | |
</div> | |
const getSlider$ = (DOM, id) => | |
DOM.select(`#${ id }`).events('input').map(e => e.target.value) | |
const intent = DOM => ({ | |
changeWeight$: getSlider$(DOM, 'weight'), | |
changeHeight$: getSlider$(DOM, 'height') | |
}) | |
const model = ({ changeWeight$, changeHeight$ }) => combineLatest( | |
changeWeight$.startWith(70), | |
changeHeight$.startWith(170), | |
(weight, height) => ({ weight, height, bmi: bmi(weight, height) }) | |
) | |
const view = state$ => | |
state$.map(({ weight, height, bmi }) => <div> | |
{ renderWeight(weight) } | |
{ renderHeight(height) } | |
<h2>BMI is { bmi }</h2> | |
</div>) | |
const main = ({ DOM }) => ({ | |
DOM: view(model(intent(DOM))) | |
}) | |
run(main, { DOM: makeDOMDriver('#app') }) |
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
import { Observable } from 'rx' | |
import { run } from '@cycle/core' | |
import { makeDOMDriver, hJSX } from '@cycle/dom' | |
import { makeHTTPDriver } from '@cycle/http' | |
const { of, just, combineLatest } = Observable | |
const square = x => x * x | |
const bmi = (weight, height) => | |
Math.round(weight / square(height * 0.01)) | |
const main = ({ DOM }) => ({ | |
DOM: combineLatest( | |
DOM.select('#weight').events('input').map(e => e.target.value).startWith(70), | |
DOM.select('#height').events('input').map(e => e.target.value).startWith(170), | |
(weight, height) => ({ weight, height, bmi: bmi(weight, height) }) | |
).map(({ weight, height, bmi }) => | |
<div> | |
<div> | |
weight { weight } kg | |
<input type="range" id="weight" min="40" max="140" value={ weight } /> | |
</div> | |
<div> | |
height { height } kg | |
<input type="range" id="height" min="140" max="210" value={ height } /> | |
</div> | |
<h2>BMI is { bmi }</h2> | |
</div> | |
) | |
}) | |
run(main, { DOM: makeDOMDriver('#app') }) |
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
import { Observable } from 'rx' | |
import { run } from '@cycle/core' | |
import { makeDOMDriver, hJSX } from '@cycle/dom' | |
import { makeHTTPDriver } from '@cycle/http' | |
const { of, just, combineLatest } = Observable | |
const square = x => x * x | |
const bmi = (weight, height) => | |
Math.round(weight / square(height * 0.01)) | |
const LabeledSlider = ({ DOM, props$ }) => { | |
const initialValue$ = props$ | |
.map(props => props.initial) | |
.first() | |
const newValue$ = DOM.select('.slider').events('input').map(e => e.target.value) | |
const value$ = initialValue$.concat(newValue$) | |
const vtree$ = combineLatest(props$, value$, (props, value) => | |
<div className="labeled-slider"> | |
<span className="label">{ props.label } { value } { props.unit }</span> | |
<input type="range" className="slider" min={ props.min } max={ props.max } value={ value }/> | |
</div> | |
) | |
return { | |
DOM: vtree$, | |
value$ | |
} | |
} | |
const style = value => ({ | |
backgroundColor: '#58D3D8', | |
width: `${ String(value) }px`, | |
height: `${ String(value) }px`, | |
borderRadius: `${ String(value * 0.5) }px` | |
}) | |
const main = ({ DOM }) => { | |
const props$ = of({ | |
label: 'Radius', unit: '', min: 10, initial: 30, max: 100 | |
}) | |
const childSources = { DOM, props$ } | |
const labeledSlider = LabeledSlider(childSources) | |
const childVTree$ = labeledSlider.DOM | |
const childValue$ = labeledSlider.value$ | |
const vtree$ = childVTree$.withLatestFrom(childValue$, | |
(childVtree, value) => <div> | |
{ childVtree } | |
<div style={ style(value) }></div> | |
</div> | |
) | |
return { | |
DOM: vtree$ | |
} | |
} | |
run(main, { | |
props$: () => of({ | |
label: 'weight', unit: 'kg', min: 40, initial: 70, max: 140 | |
}), | |
DOM: makeDOMDriver('#app') | |
}) |
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
import { Observable } from 'rx' | |
import { run } from '@cycle/core' | |
import { makeDOMDriver, hJSX } from '@cycle/dom' | |
import { makeHTTPDriver } from '@cycle/http' | |
const { of, just, combineLatest } = Observable | |
const square = x => x * x | |
const bmi = (weight, height) => | |
Math.round(weight / square(height * 0.01)) | |
const LabeledSlider = ({ DOM, props$ }) => { | |
const initialValue$ = props$ | |
.map(props => props.initial) | |
.first() | |
const newValue$ = DOM.select('.slider').events('input').map(e => e.target.value) | |
const value$ = initialValue$.concat(newValue$) | |
const vtree$ = combineLatest(props$, value$, (props, value) => | |
<div className="labeled-slider"> | |
<span className="label">{ props.label } { value } { props.unit }</span> | |
<input type="range" className="slider" min={ props.min } max={ props.max } value={ value }/> | |
</div> | |
) | |
return { | |
DOM: vtree$, | |
value$ | |
} | |
} | |
const style = value => ({ | |
backgroundColor: '#58D3D8', | |
width: `${ String(value) }px`, | |
height: `${ String(value) }px`, | |
borderRadius: `${ String(value * 0.5) }px` | |
}) | |
const main = ({ DOM }) => { | |
const weightProps$ = of({ label: 'Weight', unit: 'kg', min: 40, initial: 70, max: 150 }) | |
const heightProps$ = of({ label: 'Height', unit: 'cm', min: 140, initial: 170, max: 210 }) | |
const { isolateSource, isolateSink } = DOM | |
const weightSources = { DOM: isolateSource(DOM, 'weight'), props$: weightProps$ } | |
const heightSources = { DOM: isolateSource(DOM, 'height'), props$: heightProps$ } | |
const weightSlider = LabeledSlider(weightSources) | |
const heightSlider = LabeledSlider(heightSources) | |
const weightVTree$ = isolateSink(weightSlider.DOM, 'weight') | |
const weightValue$ = weightSlider.value$ | |
const heightVTree$ = isolateSink(heightSlider.DOM, 'height') | |
const heightValue$ = heightSlider.value$ | |
const bmi$ = combineLatest(weightValue$, heightValue$, | |
(weight, height) => bmi(weight, height)) | |
return { | |
DOM: bmi$.combineLatest(weightVTree$, heightVTree$, (bmi, weightVTree, heightVTree) => <div> | |
<div> | |
{ weightVTree } | |
{ heightVTree } | |
<h2>BMI is { bmi }</h2> | |
</div> | |
</div>) | |
} | |
} | |
run(main, { | |
props$: () => of({ | |
label: 'weight', unit: 'kg', min: 40, initial: 70, max: 140 | |
}), | |
DOM: makeDOMDriver('#app') | |
}) |
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
import { Observable } from 'rx' | |
import { run } from '@cycle/core' | |
import { makeDOMDriver, hJSX } from '@cycle/dom' | |
import { makeHTTPDriver } from '@cycle/http' | |
import isolate from '@cycle/isolate' | |
const { of, just, combineLatest } = Observable | |
const square = x => x * x | |
const bmi = (weight, height) => | |
Math.round(weight / square(height * 0.01)) | |
const LabeledSlider = ({ DOM, props$ }) => { | |
const initialValue$ = props$ | |
.map(props => props.initial) | |
.first() | |
const newValue$ = DOM.select('.slider').events('input').map(e => e.target.value) | |
const value$ = initialValue$.concat(newValue$) | |
const vtree$ = combineLatest(props$, value$, (props, value) => | |
<div className="labeled-slider"> | |
<span className="label">{ props.label } { value } { props.unit }</span> | |
<input type="range" className="slider" min={ props.min } max={ props.max } value={ value }/> | |
</div> | |
) | |
return { | |
DOM: vtree$, | |
value$ | |
} | |
} | |
const style = value => ({ | |
backgroundColor: '#58D3D8', | |
width: `${ String(value) }px`, | |
height: `${ String(value) }px`, | |
borderRadius: `${ String(value * 0.5) }px` | |
}) | |
const main = ({ DOM }) => { | |
const weightProps$ = of({ label: 'Weight', unit: 'kg', min: 40, initial: 70, max: 150 }) | |
const heightProps$ = of({ label: 'Height', unit: 'cm', min: 140, initial: 170, max: 210 }) | |
const weightSources = { DOM, props$: weightProps$ } | |
const heightSources = { DOM, props$: heightProps$ } | |
const weightSlider = isolate(LabeledSlider, 'weight')(weightSources) | |
const heightSlider = isolate(LabeledSlider, 'height')(heightSources) | |
const weightVTree$ = weightSlider.DOM | |
const weightValue$ = weightSlider.value$ | |
const heightVTree$ = heightSlider.DOM | |
const heightValue$ = heightSlider.value$ | |
const bmi$ = combineLatest(weightValue$, heightValue$, | |
(weight, height) => bmi(weight, height)) | |
return { | |
DOM: bmi$.combineLatest(weightVTree$, heightVTree$, (bmi, weightVTree, heightVTree) => <div> | |
<div> | |
{ weightVTree } | |
{ heightVTree } | |
<h2>BMI is { bmi }</h2> | |
</div> | |
</div>) | |
} | |
} | |
run(main, { | |
props$: () => of({ | |
label: 'weight', unit: 'kg', min: 40, initial: 70, max: 140 | |
}), | |
DOM: makeDOMDriver('#app') | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment