From 9bd581fea66ee80b203bcc94dd930a3417b4a491 Mon Sep 17 00:00:00 2001 From: igorbt Date: Wed, 7 Oct 2015 13:23:10 +0300 Subject: [PATCH 1/8] removed react-draggable dependency --- .../components/pages/components/sliders.jsx | 8 +- package.json | 3 - src/slider.jsx | 131 ++++++++++++------ 3 files changed, 93 insertions(+), 49 deletions(-) diff --git a/docs/src/app/components/pages/components/sliders.jsx b/docs/src/app/components/pages/components/sliders.jsx index 77c8903770b84d..aa587d0b83bf49 100644 --- a/docs/src/app/components/pages/components/sliders.jsx +++ b/docs/src/app/components/pages/components/sliders.jsx @@ -105,15 +105,15 @@ class SlidersPage extends React.Component { }, { name: 'onDragStart', - type: 'function(e, ui)', + type: 'function(e)', header: 'optional', - desc: 'Callback function that is fired when the slider has begun to move. ui contains the position information.' + desc: 'Callback function that is fired when the slider has begun to move.' }, { name: 'onDragStop', - type: 'function(e, ui)', + type: 'function(e)', header: 'optional', - desc: 'Callback function that is fried when teh slide has stopped moving. ui contains the position information.' + desc: 'Callback function that is fried when teh slide has stopped moving.' }, { name: 'onFocus', diff --git a/package.json b/package.json index e0fce83ce7bff3..2f953280f1f2fe 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,6 @@ "url": "https://github.com/callemall/material-ui/issues" }, "homepage": "http://material-ui.com/", - "dependencies": { - "react-draggable2": "^0.5.1" - }, "peerDependencies": { "react": ">=0.13", "react-tap-event-plugin": "^0.1.3" diff --git a/src/slider.jsx b/src/slider.jsx index c0b2cfce7a1c06..a982128aade269 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -1,6 +1,5 @@ const React = require('react'); const StylePropable = require('./mixins/style-propable'); -const Draggable = require('react-draggable2'); const Transitions = require('./styles/transitions'); const FocusRipple = require('./ripples/focus-ripple'); const DefaultRawTheme = require('./styles/raw-themes/light-raw-theme'); @@ -153,7 +152,7 @@ const Slider = React.createClass({ position: 'absolute', cursor: 'pointer', pointerEvents: 'inherit', - top: ((this.getTheme().handleSizeActive - this.getTheme().trackSize) / 2) + 'px', + top: 0, left: '0%', zIndex: 1, margin: (this.getTheme().trackSize / 2) + 'px 0 0 0', @@ -250,7 +249,10 @@ const Slider = React.createClass({ styles.handle, this.state.active && styles.handleWhenActive, this.state.focused && {outline: 'none'}, - this.props.disabled && styles.handleWhenDisabled + this.props.disabled && styles.handleWhenDisabled, + { + left: (percent * 100) + '%', + } ); let rippleStyle = this.mergeAndPrefix( styles.ripple, @@ -275,6 +277,16 @@ const Slider = React.createClass({ color={rippleColor}/> ); } + + let handleDragProps = {}; + + if (!this.props.disabled) { + handleDragProps = { + onTouchStart: this._onHandleTouchStart, + onMouseDown: this._onHandleMouseDown, + } + } + return (
@@ -291,18 +303,9 @@ const Slider = React.createClass({
- -
- {focusRipple} -
-
+
+ {focusRipple} +
{ + this._onDragUpdate(e, e.clientX - this._getTrackLeft()); + this._dragRunning = false; + }); + }, + + _dragTouchHandler(e) { + if (this._dragRunning) { return; } + this._dragRunning = true; + requestAnimationFrame(() => { + this._onDragUpdate(e, e.touches[0].clientX - this._getTrackLeft()); + this._dragRunning = false; + }); + }, + + _dragEndHandler(e) { + if (document) { + document.removeEventListener('mousemove', this._dragHandler, false); + document.removeEventListener('mouseup', this._dragEndHandler, false); + } + + this._onDragStop(e); + }, + + _dragTouchEndHandler(e) { + if (document) { + document.removeEventListener('touchmove', this._dragTouchHandler, false); + document.removeEventListener('touchup', this._dragTouchEndHandler, false); + document.removeEventListener('touchend', this._dragTouchEndHandler, false); + document.removeEventListener('touchcancel', this._dragTouchEndHandler, false); + } + + this._onDragStop(e); + }, + getValue() { return this.state.value; }, @@ -337,7 +396,9 @@ const Slider = React.createClass({ setPercent(percent) { let value = this._alignValue(this._percentToValue(percent)); - this.setState({value: value, percent: percent}); + let { min, max } = this.props; + let alignedPercent = (value - min) / (max - min); + this.setState({value: value, percent: alignedPercent}); }, clearValue() { @@ -350,19 +411,6 @@ const Slider = React.createClass({ return parseFloat(alignValue.toFixed(5)); }, - _constrain() { - let { min, max, step } = this.props; - let steps = (max - min) / step; - return (pos) => { - let pixelMax = React.findDOMNode(this.refs.track).clientWidth; - let pixelStep = pixelMax / steps; - let cursor = Math.round(pos.left / pixelStep) * pixelStep; - return { - left: cursor, - }; - }; - }, - _onFocus(e) { this.setState({focused: true}); if (this.props.onFocus) this.props.onFocus(e); @@ -385,39 +433,39 @@ const Slider = React.createClass({ this.setState({hovered: false}); }, + _getTrackLeft() { + return React.findDOMNode(this.refs.track).getBoundingClientRect().left; + }, + _onMouseUp(e) { if (!this.props.disabled) this.setState({active: false}); if (!this.state.dragging && Math.abs(this._pos - e.clientX) < 5) { - let pos = e.clientX - React.findDOMNode(this).getBoundingClientRect().left; + let pos = e.clientX - this._getTrackLeft(); this._dragX(e, pos); } this._pos = undefined; }, - _onMouseDownKnob() { - if (!this.props.disabled) this.setState({active: true}); - }, - - _onDragStart(e, ui) { + _onDragStart(e) { this.setState({ dragging: true, active: true, }); - if (this.props.onDragStart) this.props.onDragStart(e, ui); + if (this.props.onDragStart) this.props.onDragStart(e); }, - _onDragStop(e, ui) { + _onDragStop(e) { this.setState({ dragging: false, active: false, }); - if (this.props.onDragStop) this.props.onDragStop(e, ui); + if (this.props.onDragStop) this.props.onDragStop(e); }, - _onDragUpdate(e, ui) { + _onDragUpdate(e, pos) { if (!this.state.dragging) return; - if (!this.props.disabled) this._dragX(e, ui.position.left); + if (!this.props.disabled) this._dragX(e, pos); }, _dragX(e, pos) { @@ -429,8 +477,7 @@ const Slider = React.createClass({ _updateWithChangeEvent(e, percent) { if (this.state.percent === percent) return; this.setPercent(percent); - let value = this._alignValue(this._percentToValue(percent)); - if (this.props.onChange) this.props.onChange(e, value); + if (this.props.onChange) this.props.onChange(e, this.state.value); }, _percentToValue(percent) { From dea2c4dea852c640347af3a910e6abbf8f1f5cf8 Mon Sep 17 00:00:00 2001 From: igorbt Date: Fri, 9 Oct 2015 10:43:08 +0300 Subject: [PATCH 2/8] fixed wrong value in onChange when setState is async --- src/slider.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/slider.jsx b/src/slider.jsx index a982128aade269..8cbc1e1471bbf6 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -394,11 +394,11 @@ const Slider = React.createClass({ return this.state.percent; }, - setPercent(percent) { + setPercent(percent, callback) { let value = this._alignValue(this._percentToValue(percent)); let { min, max } = this.props; let alignedPercent = (value - min) / (max - min); - this.setState({value: value, percent: alignedPercent}); + this.setState({value: value, percent: alignedPercent}, callback); }, clearValue() { @@ -476,8 +476,9 @@ const Slider = React.createClass({ _updateWithChangeEvent(e, percent) { if (this.state.percent === percent) return; - this.setPercent(percent); - if (this.props.onChange) this.props.onChange(e, this.state.value); + this.setPercent(percent, () => { + if (this.props.onChange) this.props.onChange(e, this.state.value); + }); }, _percentToValue(percent) { From 3ca83aad051cd6fe9b1b510273fa0e18621518ce Mon Sep 17 00:00:00 2001 From: igorbt Date: Sat, 10 Oct 2015 08:49:40 +0300 Subject: [PATCH 3/8] updating value in state only if it really changes so avoiding unnecessary re-rendering and unnecessary calling of onChange from _updateWithChangeEvent. --- src/slider.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slider.jsx b/src/slider.jsx index 8cbc1e1471bbf6..3f6597028f181a 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -398,7 +398,9 @@ const Slider = React.createClass({ let value = this._alignValue(this._percentToValue(percent)); let { min, max } = this.props; let alignedPercent = (value - min) / (max - min); - this.setState({value: value, percent: alignedPercent}, callback); + if (this.state.value !== value) { + this.setState({value: value, percent: alignedPercent}, callback); + } }, clearValue() { From d2b53f34fad4569dc22e78583268129997c39528 Mon Sep 17 00:00:00 2001 From: igorbt Date: Sat, 10 Oct 2015 12:36:59 +0300 Subject: [PATCH 4/8] Removed unneded percent checking --- src/slider.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/slider.jsx b/src/slider.jsx index 3f6597028f181a..3ba4f552a1cc2c 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -477,7 +477,6 @@ const Slider = React.createClass({ }, _updateWithChangeEvent(e, percent) { - if (this.state.percent === percent) return; this.setPercent(percent, () => { if (this.props.onChange) this.props.onChange(e, this.state.value); }); From d6384e42a16a6aa54a11a41f304cff022fb5672b Mon Sep 17 00:00:00 2001 From: igorbt Date: Wed, 7 Oct 2015 13:23:10 +0300 Subject: [PATCH 5/8] removed react-draggable dependency --- .../components/pages/components/sliders.jsx | 8 +- package.json | 3 - src/slider.jsx | 132 ++++++++++++------ 3 files changed, 93 insertions(+), 50 deletions(-) diff --git a/docs/src/app/components/pages/components/sliders.jsx b/docs/src/app/components/pages/components/sliders.jsx index 77c8903770b84d..aa587d0b83bf49 100644 --- a/docs/src/app/components/pages/components/sliders.jsx +++ b/docs/src/app/components/pages/components/sliders.jsx @@ -105,15 +105,15 @@ class SlidersPage extends React.Component { }, { name: 'onDragStart', - type: 'function(e, ui)', + type: 'function(e)', header: 'optional', - desc: 'Callback function that is fired when the slider has begun to move. ui contains the position information.' + desc: 'Callback function that is fired when the slider has begun to move.' }, { name: 'onDragStop', - type: 'function(e, ui)', + type: 'function(e)', header: 'optional', - desc: 'Callback function that is fried when teh slide has stopped moving. ui contains the position information.' + desc: 'Callback function that is fried when teh slide has stopped moving.' }, { name: 'onFocus', diff --git a/package.json b/package.json index c54ad388580af5..aaf551caf24d9c 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,6 @@ "url": "https://github.com/callemall/material-ui/issues" }, "homepage": "http://material-ui.com/", - "dependencies": { - "react-draggable2": "^0.7.0-alpha1" - }, "peerDependencies": { "react": "^0.14.0", "react-dom": "^0.14.0", diff --git a/src/slider.jsx b/src/slider.jsx index 1a6851cdb7fee2..55ba00e3b023da 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -1,7 +1,6 @@ const React = require('react'); const ReactDOM = require('react-dom'); const StylePropable = require('./mixins/style-propable'); -const Draggable = require('react-draggable2'); const Transitions = require('./styles/transitions'); const FocusRipple = require('./ripples/focus-ripple'); const DefaultRawTheme = require('./styles/raw-themes/light-raw-theme'); @@ -155,7 +154,7 @@ const Slider = React.createClass({ position: 'absolute', cursor: 'pointer', pointerEvents: 'inherit', - top: ((this.getTheme().handleSizeActive - this.getTheme().trackSize) / 2) + 'px', + top: 0, left: '0%', zIndex: 1, margin: (this.getTheme().trackSize / 2) + 'px 0 0 0', @@ -252,7 +251,10 @@ const Slider = React.createClass({ styles.handle, this.state.active && styles.handleWhenActive, this.state.focused && {outline: 'none'}, - this.props.disabled && styles.handleWhenDisabled + this.props.disabled && styles.handleWhenDisabled, + { + left: (percent * 100) + '%', + } ); let rippleStyle = this.mergeAndPrefix( styles.ripple, @@ -277,6 +279,16 @@ const Slider = React.createClass({ color={rippleColor}/> ); } + + let handleDragProps = {}; + + if (!this.props.disabled) { + handleDragProps = { + onTouchStart: this._onHandleTouchStart, + onMouseDown: this._onHandleMouseDown, + } + } + return (
@@ -293,18 +305,9 @@ const Slider = React.createClass({
- -
- {focusRipple} -
-
+
+ {focusRipple} +
{ + this._onDragUpdate(e, e.clientX - this._getTrackLeft()); + this._dragRunning = false; + }); + }, + + _dragTouchHandler(e) { + if (this._dragRunning) { return; } + this._dragRunning = true; + requestAnimationFrame(() => { + this._onDragUpdate(e, e.touches[0].clientX - this._getTrackLeft()); + this._dragRunning = false; + }); + }, + + _dragEndHandler(e) { + if (document) { + document.removeEventListener('mousemove', this._dragHandler, false); + document.removeEventListener('mouseup', this._dragEndHandler, false); + } + + this._onDragStop(e); + }, + + _dragTouchEndHandler(e) { + if (document) { + document.removeEventListener('touchmove', this._dragTouchHandler, false); + document.removeEventListener('touchup', this._dragTouchEndHandler, false); + document.removeEventListener('touchend', this._dragTouchEndHandler, false); + document.removeEventListener('touchcancel', this._dragTouchEndHandler, false); + } + + this._onDragStop(e); + }, + getValue() { return this.state.value; }, @@ -339,7 +398,9 @@ const Slider = React.createClass({ setPercent(percent) { let value = this._alignValue(this._percentToValue(percent)); - this.setState({value: value, percent: percent}); + let { min, max } = this.props; + let alignedPercent = (value - min) / (max - min); + this.setState({value: value, percent: alignedPercent}); }, clearValue() { @@ -352,20 +413,6 @@ const Slider = React.createClass({ return parseFloat(alignValue.toFixed(5)); }, - _constrain() { - let { min, max, step } = this.props; - let steps = (max - min) / step; - return (pos) => { - let pixelMax = ReactDOM.findDOMNode(this.refs.track).clientWidth; - let pixelStep = pixelMax / steps; - let cursor = Math.round(pos.left / pixelStep) * pixelStep; - - return { - left: cursor, - }; - }; - }, - _onFocus(e) { this.setState({focused: true}); if (this.props.onFocus) this.props.onFocus(e); @@ -388,39 +435,39 @@ const Slider = React.createClass({ this.setState({hovered: false}); }, + _getTrackLeft() { + return ReactDOM.findDOMNode(this.refs.track).getBoundingClientRect().left; + }, + _onMouseUp(e) { if (!this.props.disabled) this.setState({active: false}); if (!this.state.dragging && Math.abs(this._pos - e.clientX) < 5) { - let pos = e.clientX - ReactDOM.findDOMNode(this).getBoundingClientRect().left; + let pos = e.clientX - this._getTrackLeft(); this._dragX(e, pos); } this._pos = undefined; }, - _onMouseDownKnob() { - if (!this.props.disabled) this.setState({active: true}); - }, - - _onDragStart(e, ui) { + _onDragStart(e) { this.setState({ dragging: true, active: true, }); - if (this.props.onDragStart) this.props.onDragStart(e, ui); + if (this.props.onDragStart) this.props.onDragStart(e); }, - _onDragStop(e, ui) { + _onDragStop(e) { this.setState({ dragging: false, active: false, }); - if (this.props.onDragStop) this.props.onDragStop(e, ui); + if (this.props.onDragStop) this.props.onDragStop(e); }, - _onDragUpdate(e, ui) { + _onDragUpdate(e, pos) { if (!this.state.dragging) return; - if (!this.props.disabled) this._dragX(e, ui.position.left); + if (!this.props.disabled) this._dragX(e, pos); }, _dragX(e, pos) { @@ -432,8 +479,7 @@ const Slider = React.createClass({ _updateWithChangeEvent(e, percent) { if (this.state.percent === percent) return; this.setPercent(percent); - let value = this._alignValue(this._percentToValue(percent)); - if (this.props.onChange) this.props.onChange(e, value); + if (this.props.onChange) this.props.onChange(e, this.state.value); }, _percentToValue(percent) { From 65939e3e0fc503e68db10bd61f2f1a2488f8fe72 Mon Sep 17 00:00:00 2001 From: igorbt Date: Fri, 9 Oct 2015 10:43:08 +0300 Subject: [PATCH 6/8] fixed wrong value in onChange when setState is async --- src/slider.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/slider.jsx b/src/slider.jsx index 55ba00e3b023da..0a590f34f58e3a 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -396,11 +396,11 @@ const Slider = React.createClass({ return this.state.percent; }, - setPercent(percent) { + setPercent(percent, callback) { let value = this._alignValue(this._percentToValue(percent)); let { min, max } = this.props; let alignedPercent = (value - min) / (max - min); - this.setState({value: value, percent: alignedPercent}); + this.setState({value: value, percent: alignedPercent}, callback); }, clearValue() { @@ -478,8 +478,9 @@ const Slider = React.createClass({ _updateWithChangeEvent(e, percent) { if (this.state.percent === percent) return; - this.setPercent(percent); - if (this.props.onChange) this.props.onChange(e, this.state.value); + this.setPercent(percent, () => { + if (this.props.onChange) this.props.onChange(e, this.state.value); + }); }, _percentToValue(percent) { From d27fbdb4268c03c7170c1d561c3b81c4067cad64 Mon Sep 17 00:00:00 2001 From: igorbt Date: Sat, 10 Oct 2015 08:49:40 +0300 Subject: [PATCH 7/8] updating value in state only if it really changes so avoiding unnecessary re-rendering and unnecessary calling of onChange from _updateWithChangeEvent. --- src/slider.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slider.jsx b/src/slider.jsx index 0a590f34f58e3a..b50d0de3f5ac41 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -400,7 +400,9 @@ const Slider = React.createClass({ let value = this._alignValue(this._percentToValue(percent)); let { min, max } = this.props; let alignedPercent = (value - min) / (max - min); - this.setState({value: value, percent: alignedPercent}, callback); + if (this.state.value !== value) { + this.setState({value: value, percent: alignedPercent}, callback); + } }, clearValue() { From bf47902446f9dbdb5ffcef7241b1f61cc8faf52f Mon Sep 17 00:00:00 2001 From: igorbt Date: Sat, 10 Oct 2015 12:36:59 +0300 Subject: [PATCH 8/8] Removed unneded percent checking --- src/slider.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/slider.jsx b/src/slider.jsx index b50d0de3f5ac41..771dd34aac3759 100644 --- a/src/slider.jsx +++ b/src/slider.jsx @@ -479,7 +479,6 @@ const Slider = React.createClass({ }, _updateWithChangeEvent(e, percent) { - if (this.state.percent === percent) return; this.setPercent(percent, () => { if (this.props.onChange) this.props.onChange(e, this.state.value); });