UNPKG

react-tangle

Version:

tangle.js style input elements for react

96 lines (90 loc) 2.63 kB
/** @jsx React.DOM */ var React = require('react'); var TangleText = React.createClass({ propTypes: { value: React.PropTypes.number.isRequired, onChange: React.PropTypes.func.isRequired, min: React.PropTypes.number, max: React.PropTypes.number, ratio: React.PropTypes.number, className: React.PropTypes.string, format: React.PropTypes.func, }, getDefaultProps: function() { return { min: -Infinity, max: Infinity, ratio: 1, className: 'react-tangle-input', format: function(x) { return x; } }; }, componentWillReceiveProps: function(nextProps) { this.setState({ value: nextProps.value }); }, getInitialState: function() { return { value: this.props.value }; }, bounds: function(num) { num = Math.max(num, this.props.min); num = Math.min(num, this.props.max); return num; }, onChange: function(e) { this.setState({ value: e.target.value }); }, onBlur: function(e) { var parsed = parseFloat(this.state.value); if (isNaN(parsed)) { this.setState({ value: this.props.value }); } else { this.props.onChange(this.bounds(parsed)); this.setState({ value: this.bounds(parsed) }); } }, onMouseMove: function(e) { var change = this.startX - e.screenX; this.dragged = true; this.setState({ value: this.bounds(this.startValue - (change * this.props.ratio)) }); }, onMouseDown: function(e) { // short circuit if currently editing number if (e.target === document.activeElement) return; e.preventDefault(); this.dragged = false; this.startX = e.screenX; this.startValue = this.state.value; window.addEventListener('mousemove', this.onMouseMove); window.addEventListener('mouseup', this.onMouseUp); }, onMouseUp: function(e) { e.preventDefault(); window.removeEventListener('mousemove', this.onMouseMove); window.removeEventListener('mouseup', this.onMouseUp); this.onBlur(); }, onClick: function(e) { // it not editing number, start to. if (!this.dragged && e.target !== document.activeElement) e.target.focus(); }, render: function() { /* jshint ignore:start */ return ( <div> <input className={this.props.className} type='text' onChange={this.onChange} onMouseDown={this.onMouseDown} onMouseUp={this.onMouseUp} onClick={this.onClick} onBlur={this.onBlur} value={this.props.format(this.state.value)} /> </div> ); /* jshint ignore:end */ } }); module.exports = TangleText;