Skip to content

Instantly share code, notes, and snippets.

@insin
Last active August 29, 2015 14:06
Show Gist options
  • Save insin/efb444d8e0390da2c7ec to your computer and use it in GitHub Desktop.
Save insin/efb444d8e0390da2c7ec to your computer and use it in GitHub Desktop.
R E A C T O M E T E R (Live version: :http://bl.ocks.org/insin/raw/efb444d8e0390da2c7ec/)
/** @jsx React.DOM */
'use strict';
var Ometer = React.createClass({
propTypes: {
leading: React.PropTypes.string
, highlight: React.PropTypes.func
, spacing: React.PropTypes.bool
, suffix: React.PropTypes.string
, trailing: React.PropTypes.string
, type: React.PropTypes.string.isRequired
, uppercase: React.PropTypes.bool
, value: React.PropTypes.oneOfType([
React.PropTypes.string
, React.PropTypes.number
])
},
getDefaultProps: function() {
return {
leading: '<<< '
, highlight: function(value) { return <strong>{value}</strong>}
, spacing: true
, suffix: 'ometer'
, trailing: ' >>>'
, uppercase: true
}
},
render: function() {
var name = (this.props.type + this.props.suffix)
if (this.props.spacing) {
name = name.split('').join(' ')
}
if (this.props.uppercase) {
name = name.toUpperCase()
}
var meter = []
for (var i = 1; i <= 10; i++) {
if (i > 1) {
meter.push(' ')
}
meter.push(i == this.props.value
? <span className="ometer__value ometer__value--selected">{this.props.highlight(i)}</span>
: <span className="ometer__value">{i}</span>)
}
return <div className={'ometer ' + this.props.type + 'ometer'}>
<div className="ometer__name">{name}</div>
<div className="ometer__meter">
<span className="ometer__bookend ometer__bookend--leading">{this.props.leading}</span>
{meter}
<span className="ometer__bookend ometer__bookend--trailing">{this.props.trailing}</span>
</div>
</div>
}
})
var App = React.createClass({
getInitialState: function() {
return {
props: {
type: 'understand'
, value: '2'
, highlight: "return '[' + v + ']'"
, leading: ''
, leading_used: true
, spacing: 'false'
, suffix: '-o-meter'
, suffix_used: true
, trailing: ''
, trailing_used: true
, uppercase: 'false'
}
}
},
onChange: function(e) {
var el = e.target
var update = {}
update[el.name] = {$set: el.type == 'checkbox' ? el.checked : el.value}
this.setState({props: React.addons.update(this.state.props, update)})
},
shouldComponentUpdate: function(nextProps, nextState) {
return (nextState.props !== this.state.props)
},
render: function() {
var invalidHighlight = false
var interactiveProps = {
type: this.state.props.type
, value: this.state.props.value
}
if (this.state.props.highlight) {
try {
interactiveProps.highlight = new Function('v', this.state.props.highlight)
}
catch (e) {
invalidHighlight = true
}
}
if (this.state.props.leading_used) { interactiveProps.leading = this.state.props.leading }
if (this.state.props.spacing) { interactiveProps.spacing = this.state.props.spacing == 'true' }
if (this.state.props.suffix_used) { interactiveProps.suffix = this.state.props.suffix }
if (this.state.props.trailing_used) { interactiveProps.trailing = this.state.props.trailing }
if (this.state.props.uppercase) { interactiveProps.uppercase = this.state.props.uppercase == 'true' }
return <div>
<p>
A React <code>&lt;Ometer&gt;</code> component for displaying ratings on
a 1-to-10 scale, based on <a href="http://www.rllmukforum.com/">RLLMUK</a>'s
world famous Dreamcastometer, which measures how doomed something is on a scale
of 1 to Dreamcast (10).
</p>
<h2>Default</h2>
<p>
The default <code>&lt;Ometer&gt;</code> is based on the classic Dreamcastometer.
</p>
<dl>
<dt>Code:</dt>
<dd><pre><code>&lt;Ometer type="dreamcast" value="8"/&gt;</code></pre></dd>
<dt>Result:</dt>
<dd><Ometer type="dreamcast" value="8"/></dd>
</dl>
<h2>All Props</h2>
<p>An interactive example showing all available <code>&lt;Ometer&gt;</code> props.</p>
<dl>
<dt>Code:</dt>
<dd onChange={this.onChange}><pre><code>&lt;Ometer<br/>
&nbsp;&nbsp;type="<input name="type" id="type" value={this.state.props.type} required/>"<br/>
&nbsp;&nbsp;value="<input type="number" min="1" max="10" name="value" value={this.state.props.value} step="1" size="2" required/>"<br/>
&nbsp;&nbsp;highlight=&#123;function(v) &#123; <input name="highlight" value={this.state.props.highlight}/> &#125;&#125; {invalidHighlight && <span>(Invalid JavaScript)</span>}<br/>
&nbsp;&nbsp;<input type="checkbox" name="leading_used" checked={this.state.props.leading_used}/>leading="<input name="leading" value={this.state.props.leading}/>"<br/>
&nbsp;&nbsp;spacing=&#123;<select name="spacing" value={this.state.props.spacing}><option>true</option><option>false</option></select>&#125;<br/>
&nbsp;&nbsp;<input type="checkbox" name="suffix_used" checked={this.state.props.suffix_used}/>suffix="<input name="suffix" value={this.state.props.suffix}/>"<br/>
&nbsp;&nbsp;<input type="checkbox" name="trailing_used" checked={this.state.props.trailing_used}/>trailing="<input name="trailing" value={this.state.props.trailing}/>"<br/>
&nbsp;&nbsp;uppercase=&#123;<select name="uppercase" value={this.state.props.uppercase}><option>true</option><option>false</option></select>&#125;<br/>
/&gt;</code></pre></dd>
<dt>Result:</dt>
<dd>
{Ometer(interactiveProps)}
</dd>
</dl>
</div>
}
})
React.renderComponent(<App/>, document.getElementById('app'))
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>R E A C T O M E T E R</title>
<script src="http://fb.me/react-with-addons-0.11.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.11.2.js"></script>
<style>
body {
font-size: 16px;
font-family: helvetica, arial, sans-serif;
}
</style>
</head>
<body>
<h1>R E A C T O M E T E R</h1>
<div id="app"></div>
<script type="text/jsx" src="app.jsx"></script>
<a href="https://gist.github.com/insin/efb444d8e0390da2c7ec"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment