Skip to content

Commit

Permalink
feat: Add callback notifying the start of any interaction (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
oyeanuj authored and davidchin committed Mar 10, 2017
1 parent 343e655 commit 4ca6ea2
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 3 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ Set a name for your form component.

Whenever your user interacts with your component (i.e.: dragging a slider), this function gets called. Inside the function, you should assign the new value to your component.

#### onChangeStart: (value: number | Range): void

Whenever your user starts interacting with your component (i.e.: `onMouseDown`, or `onTouchStart`), this function gets called.

#### onChangeComplete: (value: number | Range): void

Every mouse / touch event can trigger multiple updates, therefore causing `onChange` callback to fire multiple times. On the other hand, `onChangeComplete` callback only gets called when the user stops dragging.
Expand Down
1 change: 1 addition & 0 deletions example/js/example-app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default class ExampleApp extends React.Component {
formatLabel={value => value.toFixed(2)}
value={this.state.value3}
onChange={value => this.setState({ value3: value })}
onChangeStart={value => console.log('onChangeStart with value =', value)}
onChangeComplete={value => console.log(value)} />

<InputRange
Expand Down
1 change: 1 addition & 0 deletions react-input-range.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ declare interface InputRangeProps {
minValue?: number;
name?: string;
onChange: (value: Range | number) => void;
onChangeStart?: (value: Range | number) => void;
onChangeComplete?: (value: Range | number) => void;
step?: number;
value: Range | number;
Expand Down
10 changes: 7 additions & 3 deletions src/js/input-range/input-range.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default class InputRange extends React.Component {
maxValue: rangePropType,
minValue: rangePropType,
name: React.PropTypes.string,
onChangeStart: React.PropTypes.func,
onChange: React.PropTypes.func.isRequired,
onChangeComplete: React.PropTypes.func,
step: React.PropTypes.number,
Expand Down Expand Up @@ -64,6 +65,7 @@ export default class InputRange extends React.Component {
* @param {string} [props.name]
* @param {string} props.onChange
* @param {Function} [props.onChangeComplete]
* @param {Function} [props.onChangeStart]
* @param {number} [props.step = 1]
* @param {number|Range} props.value
*/
Expand Down Expand Up @@ -410,11 +412,13 @@ export default class InputRange extends React.Component {
*/
@autobind
handleInteractionStart() {
if (!this.props.onChangeComplete || isDefined(this.startValue)) {
return;
if (this.props.onChangeStart) {
this.props.onChangeStart(this.props.value);
}

this.startValue = this.props.value;
if (this.props.onChangeComplete && !isDefined(this.startValue)) {
this.startValue = this.props.value;
}
}

/**
Expand Down
24 changes: 24 additions & 0 deletions test/input-range/input-range.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,30 @@ describe('InputRange', () => {
component.detach();
});

it('notifies the parent component when dragging starts', () => {
const onChange = jasmine.createSpy('onChange').and.callFake(value => component.setProps({ value }));
const onChangeStart = jasmine.createSpy('onChangeStart');
const jsx = (
<InputRange
maxValue={20}
minValue={0}
value={{ min: 2, max: 10 }}
onChange={value => component.setProps({ value })}
onChangeStart={onChangeStart}
/>
);
const component = mount(jsx, { attachTo: container });
const slider = component.find(`Slider [onMouseDown]`).first();

slider.simulate('mouseDown', { clientX: 50, clientY: 50 });
document.dispatchEvent(new MouseEvent('mousemove', { clientX: 100, clientY: 50 }));
document.dispatchEvent(new MouseEvent('mousemove', { clientX: 150, clientY: 50 }));
document.dispatchEvent(new MouseEvent('mouseup', { clientX: 150, clientY: 50 }));
expect(onChangeStart.calls.count()).toEqual(1);

component.detach();
});

it('notifies the parent component when dragging stops', () => {
const onChange = jasmine.createSpy('onChange').and.callFake(value => component.setProps({ value }));
const onChangeComplete = jasmine.createSpy('onChangeComplete');
Expand Down

0 comments on commit 4ca6ea2

Please sign in to comment.