rclass = React.createClass
rtypes = React.PropTypes
log = (s...) -> console.log(s...)
uniqueId = (s) -> "#{s}#{Math.random()}"
AnswerRadioInput = rclass
propTypes:
id : rtypes.string
name : rtypes.string.isRequired
label : rtypes.string.isRequired
value : rtypes.string.isRequired
checked : rtypes.bool
onChanged : rtypes.func.isRequired
getDefaultProps: ->
id : null
checked : false
componentWillReceiveProps: (nextProps) ->
if nextProps.checked?
@setState(checked:nextProps.checked)
getInitialState: ->
id = if @props.id then @props.id else uniqueId("radio-")
checked : !!@props.checked
id : id
name : id
handleChanged: (e) ->
checked = e.target.checked
@setState(checked : checked)
if checked
@props.onChanged(@props.value)
render: ->
<div className="radio">
<label htmlFor={@props.id}>
<input type="radio"
name = {@props.name}
id = {@props.id}
value = {@props.value}
checked = {@state.checked}
onChange = {@handleChanged}
/>
{@props.label}
</label>
</div>
AnswerMultipleChoiceQuestion = rclass
propTypes:
value : rtypes.string
choices : rtypes.array.isRequired
onCompleted : rtypes.func.isRequired
getInitialState: ->
id : uniqueId('multiple-choices-')
value : @props.value
handleChanged: (value) ->
log("AnswerMultipleChoiceQuestion.handleChanged ", value)
@setState(value:value)
@props.onCompleted(value)
renderChoices: ->
for choice, i in @props.choices
<AnswerRadioInput
id = {"choice-#{i}"}
key = {"choice-#{i}"}
name = {@state.id}
label = {choice}
value = {choice}
checked = {@state.value == choice}
onChanged = {@handleChanged}
/>
render: ->
<div className="form-group">
<Timer />
<label className="survey-item-label" htmlFor={@state.id}>
{@props.label}
</label>
<div className="survey-item-content">
{@renderChoices()}
</div>
</div>
NeatComponent = rclass
render: ->
<div className="neat-component">
{<h1>Showing this title</h1> if @props.showTitle}
<hr />
{<p key={n}>This line has been printed {n} times</p> for n in [1..5]}
</div>
NeatComponent2 = rclass
title: ->
if @props.showTitle
<h1>Showing this title</h1>
else
<h2>Instead, just a subtitle</h2>
loop0: ->
for n in [1..10]
<div key={n}>Line {n}</div>
loop: ->
(<div key={n}>Line {n}</div> for n in [1..3])
render: ->
<div className="neat-component">
<NeatComponent />
{@title()}
<hr />
{@loop()}
</div>
Timer = rclass
getInitialState: ->
secondsElapsed : 0
tick: () ->
@setState(secondsElapsed : @state.secondsElapsed + 1)
componentDidMount: ->
@interval = setInterval(@tick, 1000)
componentWillUnmount: ->
clearInterval(@interval)
render: ->
<div> Seconds Elapsed: {@state.secondsElapsed} </div>
IntervalMixin =
setInterval : (cb, interval) ->
token = setInterval(cb, interval)
@__intervals.push(token)
return token
componentDidMount: ->
@__intervals = []
componentWillUnmount: ->
(clearInterval(token) for token in @__intervals)
Since2014 = rclass
mixins : [IntervalMixin]
componentDidMount: ->
@setInterval(@forceUpdate.bind(@), 1000)
render: ->
from = Number(new Date(2014,0,1))
to = Date.now()
return <div>Seconds since 2014: {Math.round((to-from)/1000)}</div>
DoodleArea = rclass
render : ->
<div>
Describe your doodle: <RichText />
<canvas ref="mainCanvas" width="200" height="100" style={border:'1px solid #000000'} />
</div>
componentDidMount: ->
canvasNode = @refs.mainCanvas.getDOMNode()
ctx = canvasNode.getContext("2d")
ctx.fillStyle = "#0000ff"
ctx.fillRect(0,0,150,75)
RichText = rclass
render : ->
<div ref="editableDiv" contentEditable="true"
width="200" height="100"
style={border:'1px solid #000000'}
onKeyUp={@handleKeyUp} >
{window.localStorage.doodle}</div>
handleKeyUp: ->
editor = @refs.editableDiv.getDOMNode()
html = editor.innerHTML
window.localStorage.doodle = html
console.log(html)
MyForm = rclass
submitHandler : (event) ->
event.preventDefault()
helloTo = @refs.helloTo.getDOMNode().value
log(helloTo)
render: ->
<form onSubmit={@submitHandler}>
<input ref="helloTo"
type="text"
defaultValue="Hello World!" />
<br />
<button type="submit">Speak</button>
</form>
MyForm2 = rclass
getInitialState: ->
helloTo: 'Hello world!'
handleChange: (event) ->
@setState(helloTo:event.target.value.toUpperCase())
submitHandler: (event) ->
event.preventDefault()
log(@state.helloTo)
render: ->
<form onSubmit={@submitHandler}>
<input type="text"
value={@state.helloTo}
onChange={@handleChange} />
<br />
({@state.helloTo.length} characters)
<button type='submit'>Speak</button>
</form>
NumberComponent = rclass
render : ->
<div>{@props.number}</div>
num = Math.random()
console.log(React.renderToString(<NumberComponent number={num}/>))
<NumberComponent number=}
done = (event) ->
console.log("done", event)
the_choices = ['First', 'Next', 'Last', 'Final Option']
page = ->
<div>
<MyForm />
<MyForm2 />
<DoodleArea />
<Since2014 />
<h1>React Testbed</h1>
<Timer />
<hr />
<AnswerMultipleChoiceQuestion
choices={the_choices} onCompleted=done />
</div>
console.log(React.renderToString(page()))
console.log(React.renderToStaticMarkup(page()))
React.render page(), document.getElementById('example')