Skip to content

Commit 30e7e72

Browse files
committed
add click-hold functionality
1 parent 0b278fb commit 30e7e72

File tree

5 files changed

+303
-307
lines changed

5 files changed

+303
-307
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
1.2.0 (2018-12-12)
2+
------------------
3+
* Add hold option, enabled by default.
4+
15
1.1.0 (2018-10-10)
26
------------------
37
* Fix and standardize import

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ NODE_MODULES ?= ./node_modules
22
JS_SENTINAL ?= $(NODE_MODULES)/sentinal
33

44
$(JS_SENTINAL): package.json
5-
rm -rf $(NODE_MODULES)
5+
rm -rf $(NODE_MODULES) package-lock.json
66
npm install
77
touch $(JS_SENTINAL)
88

lib/RangeStepInput.jsx

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@ export default class RangeStepInput extends React.Component {
2020
this.onMouseDown = this.onMouseDown.bind(this);
2121
this.onMouseUp = this.onMouseUp.bind(this);
2222
this.onMouseMove = this.onMouseMove.bind(this);
23+
24+
this.domRef = React.createRef();
2325
}
2426
render() {
2527
return <input
2628
type="range"
29+
ref={this.domRef}
2730
className={this.props.className}
2831
min={this.props.min}
2932
max={this.props.max}
3033
step={this.props.step}
3134
value={this.props.value}
3235
name={this.props.name}
3336
id={this.props.id}
37+
disabled={this.props.disabled}
3438
onChange={this.props.onChange}
3539
onMouseDown={this.onMouseDown}
3640
onMouseUp={this.onMouseUp}
@@ -40,12 +44,25 @@ export default class RangeStepInput extends React.Component {
4044
}
4145
onMouseDown() {
4246
this.setState({isMouseDown: true});
47+
48+
if (this.props.hold) {
49+
const oldVal = this.props.value;
50+
const self = this;
51+
// Add some initial delay on the click-hold functionality.
52+
setTimeout(function() {
53+
self.holdLoop = self.makeHoldLoop(oldVal);
54+
}, 600);
55+
}
4356
}
4457
onMouseUp() {
4558
this.setState({
4659
isMouseDown: false,
4760
isDragging: false
4861
});
62+
63+
if (this.holdLoop) {
64+
clearInterval(this.holdLoop);
65+
}
4966
}
5067
onMouseMove() {
5168
if (this.state.isMouseDown) {
@@ -67,7 +84,45 @@ export default class RangeStepInput extends React.Component {
6784
oldVal + step : oldVal - step;
6885
}
6986
}
70-
}
87+
makeHoldLoop(oldVal) {
88+
const self = this;
89+
90+
return setInterval(function() {
91+
if (!self.state.isMouseDown) {
92+
// The user isn't holding the cursor anymore: clean up
93+
// and cancel.
94+
if (self.holdLoop) {
95+
clearInterval(self.holdLoop);
96+
}
97+
return false;
98+
}
99+
100+
const input = self.domRef.current;
101+
102+
let newVal = self.props.value;
103+
if (oldVal > newVal) {
104+
newVal -= self.props.step;
105+
} else if (oldVal < newVal) {
106+
newVal += self.props.step;
107+
} else {
108+
// The user is just holding the cursor at the current
109+
// value, so don't do anything.
110+
return false;
111+
}
112+
113+
// Directly setting input.value will cause the new value
114+
// to not be recognized, because of React.
115+
// https://stackoverflow.com/a/46012210/173630
116+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
117+
window.HTMLInputElement.prototype, 'value').set;
118+
nativeInputValueSetter.call(input, newVal);
119+
120+
// Trigger an onChange event.
121+
const e = new Event('change', {bubbles: true});
122+
return input.dispatchEvent(e);
123+
}, 100);
124+
}
125+
};
71126

72127
RangeStepInput.propTypes = {
73128
value: PropTypes.number.isRequired,
@@ -77,5 +132,14 @@ RangeStepInput.propTypes = {
77132
min: PropTypes.number,
78133
max: PropTypes.number,
79134
id: PropTypes.string,
80-
name: PropTypes.string
135+
name: PropTypes.string,
136+
disabled: PropTypes.bool,
137+
138+
// Determines whether the slider changes value when the cursor is
139+
// held on it.
140+
hold: PropTypes.bool
141+
};
142+
143+
RangeStepInput.defaultProps = {
144+
hold: true
81145
};

0 commit comments

Comments
 (0)