From 82692a77b263bd9ec38f1567a9e94b786b9d4879 Mon Sep 17 00:00:00 2001 From: Jan Amann Date: Wed, 10 Oct 2018 13:10:16 +0200 Subject: [PATCH] Fix dragging the slider on iOS. --- example/js/example-app.jsx | 11 ++++++++++ example/scss/index.scss | 21 ++++++++++++++++++ src/js/input-range/input-range.jsx | 34 ++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/example/js/example-app.jsx b/example/js/example-app.jsx index f09d307..7e3b813 100644 --- a/example/js/example-app.jsx +++ b/example/js/example-app.jsx @@ -23,6 +23,7 @@ export default class ExampleApp extends React.Component { min: 3, max: 7, }, + value7: 4, }; } @@ -77,6 +78,16 @@ export default class ExampleApp extends React.Component { onChange={value => this.setState({ value6: value })} onChangeComplete={value => console.log(value)} value={this.state.value6} /> + +
+ null} + minValue={0} + value={this.state.value7} + onChange={value => this.setState({ value7: value })} + onChangeComplete={value => console.log(value)} /> +
); } diff --git a/example/scss/index.scss b/example/scss/index.scss index 92da23e..875ecd7 100644 --- a/example/scss/index.scss +++ b/example/scss/index.scss @@ -10,3 +10,24 @@ .input-range { margin-bottom: 160px; } + +.touch-friendly { + .input-range { + &__track { + height: 30px; + + &--active { + background: rgba(#3f51b5, 0.5) + } + } + + &__slider { + width: 40px; + height: 40px; + + &-container { + top: 5px; + } + } + } +} diff --git a/src/js/input-range/input-range.jsx b/src/js/input-range/input-range.jsx index a097d4f..d5a179f 100644 --- a/src/js/input-range/input-range.jsx +++ b/src/js/input-range/input-range.jsx @@ -108,12 +108,17 @@ export default class InputRange extends React.Component { this.lastKeyMoved = null; } + componentDidMount() { + this.addNodeTouchStartListener(); + } + /** * @ignore * @override * @return {void} */ componentWillUnmount() { + this.removeNodeTouchStartListener(); this.removeDocumentMouseUpListener(); this.removeDocumentTouchEndListener(); } @@ -320,6 +325,22 @@ export default class InputRange extends React.Component { this.updateValue(key, value); } + /** + * Start listening to touchstart events on the node + * @private + * @return {void} + */ + addNodeTouchStartListener() { + // Adding a `onTouchStart` prop to the node doesn't work, as the + // event handler will be added as `passive`. The handler needs to + // be active, so it is able to call `preventDefault()`. Otherwise + // e.g. the page scrolls while dragging slightly vertically. + this.node.addEventListener('touchstart', this.handleTouchStart, { + passive: false, + }); + } + + /** * Listen to mouseup event * @private @@ -349,6 +370,15 @@ export default class InputRange extends React.Component { this.node.ownerDocument.removeEventListener('mouseup', this.handleMouseUp); } + /** + * Stop listening to touchstart events on the node + * @private + * @return {void} + */ + removeNodeTouchStartListener() { + this.node.removeEventListener('touchstart', this.handleTouchStart); + } + /** * Stop listening to touchend event * @private @@ -565,6 +595,7 @@ export default class InputRange extends React.Component { handleTouchStart(event) { this.handleInteractionStart(event); this.addDocumentTouchEndListener(); + event.preventDefault(); } /** @@ -663,8 +694,7 @@ export default class InputRange extends React.Component { className={componentClassName} onKeyDown={this.handleKeyDown} onKeyUp={this.handleKeyUp} - onMouseDown={this.handleMouseDown} - onTouchStart={this.handleTouchStart}> + onMouseDown={this.handleMouseDown}>