Skip to content

Commit

Permalink
Merge pull request #153 from mikepb/master
Browse files Browse the repository at this point in the history
Trigger onChange when clicking on slider
  • Loading branch information
Hai Nguyen committed Dec 20, 2014
2 parents 7202a2c + ef7adeb commit a29de58
Showing 1 changed file with 175 additions and 1 deletion.
176 changes: 175 additions & 1 deletion src/js/slider.jsx
Original file line number Diff line number Diff line change
@@ -1 +1,175 @@
/** * @jsx React.DOM */var React = require('react'), Paper = require('./paper.jsx'), Classable = require('./mixins/classable.js'), Draggable = require('react-draggable2');var Slider = React.createClass({ propTypes: { required: React.PropTypes.bool, disabled: React.PropTypes.bool, min: React.PropTypes.number, max: React.PropTypes.number, step: React.PropTypes.number, error: React.PropTypes.string, description: React.PropTypes.string, name: React.PropTypes.string.isRequired, onChange: React.PropTypes.func }, mixins: [Classable], getDefaultProps: function() { return { required: true, disabled: false, defaultValue: 0, min: 0, max: 1, dragging: false }; }, getInitialState: function() { var value = this.props.value; if (value == null) value = this.props.defaultValue; var percent = value / this.props.max; if (isNaN(percent)) percent = 0; return { value: value, percent: percent } }, componentWillReceiveProps: function(nextProps) { if (nextProps.value != null) { this.setValue(nextProps.value); } }, render: function() { var classes = this.getClasses('mui-input', { 'mui-error': this.props.error != null }); var sliderClasses = this.getClasses('mui-slider', { 'mui-slider-zero': this.state.percent == 0, 'mui-disabled': this.props.disabled }); var percent = this.state.percent; if (percent > 1) percent = 1; else if (percent < 0) percent = 0; return ( <div className={classes}> <span className="mui-input-highlight"></span> <span className="mui-input-bar"></span> <span className="mui-input-description">{this.props.description}</span> <span className="mui-input-error">{this.props.error}</span> <div className={sliderClasses} onClick={this._onClick}> <div ref="track" className="mui-slider-track"> <Draggable axis="x" bound="point" cancel={this.props.disabled ? '*' : null} start={{x: (percent * 100) + '%'}} onStart={this._onDragStart} onStop={this._onDragStop} onDrag={this._onDragUpdate}> <div className="mui-slider-handle" tabIndex={0}></div> </Draggable> <div className="mui-slider-selection mui-slider-selection-low" style={{width: (percent * 100) + '%'}}> <div className="mui-slider-selection-fill"></div> </div> <div className="mui-slider-selection mui-slider-selection-high" style={{width: ((1 - percent) * 100) + '%'}}> <div className="mui-slider-selection-fill"></div> </div> </div> </div> <input ref="input" type="hidden" name={this.props.name} value={this.state.value} required={this.props.required} min={this.props.min} max={this.props.max} step={this.props.step} /> </div> ); }, getValue: function() { return this.state.value; }, setValue: function(i) { // calculate percentage var percent = (i - this.props.min) / (this.props.max - this.props.min); if (isNaN(percent)) percent = 0; // update state this.setState({ value: i, percent: percent }); }, getPercent: function() { return this.state.percent; }, setPercent: function (percent) { var value = percent * (this.props.max - this.props.min) + this.props.min; this.setState({value: value, percent: percent}); }, clearValue: function() { this.setValue(0); }, _onClick: function (e) { // let draggable handle the slider if (this.state.dragging || this.props.disabled) return; var node = this.refs.track.getDOMNode(); var boundingClientRect = node.getBoundingClientRect(); var offset = e.clientX - boundingClientRect.left; var percent = offset / node.clientWidth; this.setPercent(percent); }, _onDragStart: function(e, ui) { this.setState({ dragging: true }); }, _onDragStop: function(e, ui) { this.setState({ dragging: false }); }, _onDragUpdate: function(e, ui) { if (!this.state.dragging) return; var value = this.state.value; if (!this.props.disabled) this._dragX(ui.position.left); if (this.state.value != value && this.props.onChange) { this.props.onChange(e, this.state.value); } }, _dragX: function(pos) { var max = this.refs.track.getDOMNode().clientWidth; if (pos < 0) pos = 0; else if (pos > max) pos = max; this.setPercent(pos / max); }});module.exports = Slider;

var React = require('react'),
Paper = require('./paper.jsx'),
Classable = require('./mixins/classable.js'),
Draggable = require('react-draggable2');

var Slider = React.createClass({

propTypes: {
required: React.PropTypes.bool,
disabled: React.PropTypes.bool,
min: React.PropTypes.number,
max: React.PropTypes.number,
step: React.PropTypes.number,
error: React.PropTypes.string,
description: React.PropTypes.string,
name: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func
},

mixins: [Classable],

getDefaultProps: function() {
return {
required: true,
disabled: false,
defaultValue: 0,
min: 0,
max: 1,
dragging: false
};
},

getInitialState: function() {
var value = this.props.value;
if (value == null) value = this.props.defaultValue;
var percent = value / this.props.max;
if (isNaN(percent)) percent = 0;
return {
value: value,
percent: percent
}
},

componentWillReceiveProps: function(nextProps) {
if (nextProps.value != null) {
this.setValue(nextProps.value);
}
},

render: function() {
var classes = this.getClasses('mui-input', {
'mui-error': this.props.error != null
});

var sliderClasses = this.getClasses('mui-slider', {
'mui-slider-zero': this.state.percent == 0,
'mui-disabled': this.props.disabled
});

var percent = this.state.percent;
if (percent > 1) percent = 1; else if (percent < 0) percent = 0;

return (
<div className={classes}>
<span className="mui-input-highlight"></span>
<span className="mui-input-bar"></span>
<span className="mui-input-description">{this.props.description}</span>
<span className="mui-input-error">{this.props.error}</span>
<div className={sliderClasses} onClick={this._onClick}>
<div ref="track" className="mui-slider-track">
<Draggable axis="x" bound="point"
cancel={this.props.disabled ? '*' : null}
start={{x: (percent * 100) + '%'}}
onStart={this._onDragStart}
onStop={this._onDragStop}
onDrag={this._onDragUpdate}>
<div className="mui-slider-handle" tabIndex={0}></div>
</Draggable>
<div className="mui-slider-selection mui-slider-selection-low"
style={{width: (percent * 100) + '%'}}>
<div className="mui-slider-selection-fill"></div>
</div>
<div className="mui-slider-selection mui-slider-selection-high"
style={{width: ((1 - percent) * 100) + '%'}}>
<div className="mui-slider-selection-fill"></div>
</div>
</div>
</div>
<input ref="input" type="hidden"
name={this.props.name}
value={this.state.value}
required={this.props.required}
min={this.props.min}
max={this.props.max}
step={this.props.step} />
</div>
);
},

getValue: function() {
return this.state.value;
},

setValue: function(i) {
// calculate percentage
var percent = (i - this.props.min) / (this.props.max - this.props.min);
if (isNaN(percent)) percent = 0;
// update state
this.setState({
value: i,
percent: percent
});
},

getPercent: function() {
return this.state.percent;
},

setPercent: function (percent) {
var value = this._percentToValue(percent);
this.setState({value: value, percent: percent});
},

clearValue: function() {
this.setValue(0);
},

_onClick: function (e) {
// let draggable handle the slider
if (this.state.dragging || this.props.disabled) return;
var value = this.state.value;
var node = this.refs.track.getDOMNode();
var boundingClientRect = node.getBoundingClientRect();
var offset = e.clientX - boundingClientRect.left;
this._updateWithChangeEvent(e, offset / node.clientWidth);
},

_onDragStart: function(e, ui) {
this.setState({
dragging: true
});
},

_onDragStop: function(e, ui) {
this.setState({
dragging: false
});
},

_onDragUpdate: function(e, ui) {
if (!this.state.dragging) return;
if (!this.props.disabled) this._dragX(e, ui.position.left);
},

_dragX: function(e, pos) {
var max = this.refs.track.getDOMNode().clientWidth;
if (pos < 0) pos = 0; else if (pos > max) pos = max;
this._updateWithChangeEvent(e, pos / max);
},

_updateWithChangeEvent: function(e, percent) {
if (this.state.percent === percent) return;
this.setPercent(percent);
var value = this._percentToValue(percent);
if (this.props.onChange) this.props.onChange(e, value);
},

_percentToValue: function(percent) {
return percent * (this.props.max - this.props.min) + this.props.min;
}

});

module.exports = Slider;

0 comments on commit a29de58

Please sign in to comment.