From 395fa6c20104148235acdd6b7b234beb83bad8a1 Mon Sep 17 00:00:00 2001 From: Benjy Cui Date: Fri, 11 Dec 2015 09:57:54 +0800 Subject: [PATCH] feat: add `allowCross` property #56 --- README.md | 6 ++++++ examples/range.js | 4 ++-- src/Slider.jsx | 46 +++++++++++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c475549..bfad15f 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,12 @@ ReactDOM.render(, container); false Determines the type of slider. If range is `true`, two handles will be rendered in order to select a range. + + allowCross + boolean + true + When `range` is `true`, `allowCross` could be set as `true` to allow those two handles cross. + defaultValue number or [number, number] diff --git a/examples/range.js b/examples/range.js index e97263d..0e3537b 100644 --- a/examples/range.js +++ b/examples/range.js @@ -50,8 +50,8 @@ const CustomizedRange = React.createClass({ ReactDOM.render(
-

Basic Range

- +

Basic Range,`allowCross`

+

Basic Range,`step=20`

diff --git a/src/Slider.jsx b/src/Slider.jsx index 76cd574..2e154e5 100644 --- a/src/Slider.jsx +++ b/src/Slider.jsx @@ -98,19 +98,16 @@ class Slider extends React.Component { } } - onChange(handle, value) { + onChange(state) { const props = this.props; const isNotControlled = !('value' in props); if (isNotControlled) { - this.setState({[handle]: value}); + this.setState(state); + } else if (state.handle) { + this.setState({handle: state.handle}); } - const state = this.state; - const data = { - upperBound: state.upperBound, - lowerBound: state.lowerBound, - }; - data[handle] = value; + const data = objectAssign({}, this.state, state); const changedValue = props.range ? [data.lowerBound, data.upperBound] : data.upperBound; props.onChange(changedValue); } @@ -142,7 +139,26 @@ class Slider extends React.Component { const oldValue = state[state.handle]; if (value === oldValue) return; - this.onChange(state.handle, value); + if (props.allowCross && value < state.lowerBound && state.handle === 'upperBound') { + this.onChange({ + handle: 'lowerBound', + lowerBound: value, + upperBound: this.state.lowerBound, + }); + return; + } + if (props.allowCross && value > state.upperBound && state.handle === 'lowerBound') { + this.onChange({ + handle: 'upperBound', + upperBound: value, + lowerBound: this.state.upperBound, + }); + return; + } + + this.onChange({ + [state.handle]: value, + }); } onTouchStart(e) { @@ -197,7 +213,9 @@ class Slider extends React.Component { const oldValue = state[valueNeedChanging]; if (value === oldValue) return; - this.onChange(valueNeedChanging, value); + this.onChange({ + [valueNeedChanging]: value, + }); } getValue() { @@ -238,7 +256,7 @@ class Slider extends React.Component { trimAlignValue(v, nextProps) { const state = this.state || {}; const {handle, lowerBound, upperBound} = state; - const {marks, step, min, max} = objectAssign({}, this.props, nextProps || {}); + const {marks, step, min, max, allowCross} = objectAssign({}, this.props, nextProps || {}); let val = v; if (val <= min) { @@ -247,10 +265,10 @@ class Slider extends React.Component { if (val >= max) { val = max; } - if (handle === 'upperBound' && val <= lowerBound) { + if (!allowCross && handle === 'upperBound' && val <= lowerBound) { val = lowerBound; } - if (handle === 'lowerBound' && val >= upperBound) { + if (!allowCross && handle === 'lowerBound' && val >= upperBound) { val = upperBound; } @@ -384,6 +402,7 @@ Slider.propTypes = { tipFormatter: React.PropTypes.func, dots: React.PropTypes.bool, range: React.PropTypes.bool, + allowCross: React.PropTypes.bool, }; Slider.defaultProps = { @@ -401,6 +420,7 @@ Slider.defaultProps = { disabled: false, dots: false, range: false, + allowCross: true, }; export default Slider;