Skip to content

Instantly share code, notes, and snippets.

@namelos
Last active March 6, 2016 16:37
Show Gist options
  • Save namelos/725a4e82f7c0f3a7ea64 to your computer and use it in GitHub Desktop.
Save namelos/725a4e82f7c0f3a7ea64 to your computer and use it in GitHub Desktop.
cycle bmi calculator example
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') })
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') })
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')
})
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')
})
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