Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/js/example-app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class ExampleApp extends React.Component {
return (
<form className="form">
<InputRange
showHoverLabel
maxValue={20}
minValue={0}
value={this.state.value}
Expand Down
150 changes: 148 additions & 2 deletions src/js/input-range/input-range.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default class InputRange extends React.Component {
onChangeComplete: React.PropTypes.func,
step: React.PropTypes.number,
value: valuePropType,
showHoverLabel: React.PropTypes.bool,
};
}

Expand All @@ -49,6 +50,7 @@ export default class InputRange extends React.Component {
maxValue: 10,
minValue: 0,
step: 1,
showHoverLabel: false,
};
}

Expand All @@ -66,6 +68,7 @@ export default class InputRange extends React.Component {
* @param {Function} [props.onChangeComplete]
* @param {number} [props.step = 1]
* @param {number|Range} props.value
* @param {Boolean} [props.showHoverLabel = false]
*/
constructor(props) {
super(props);
Expand All @@ -87,6 +90,18 @@ export default class InputRange extends React.Component {
* @type {?Component}
*/
this.trackNode = null;

/**
* @private
* @type {?Component}
*/
this.hoverLabel = null;


this.state = {
hovering: false,
hoverValue: props.value,
};
}

/**
Expand Down Expand Up @@ -308,6 +323,7 @@ export default class InputRange extends React.Component {
this.node.ownerDocument.addEventListener('mouseup', this.handleMouseUp);
}


/**
* Listen to touchend event
* @private
Expand All @@ -327,6 +343,33 @@ export default class InputRange extends React.Component {
this.node.ownerDocument.removeEventListener('mouseup', this.handleMouseUp);
}

/**
* Stop listening to mouseover event
* @private
* @return {void}
*/
removeDocumentMouseOverListener() {
this.node.ownerDocument.removeEventListener('mouseover', this.handleMouseOver);
}

/**
* Stop listening to mouseout event
* @private
* @return {void}
*/
removeDocumentMouseOutListener() {
this.node.ownerDocument.removeEventListener('mouseout', this.handleMouseOut);
}

/**
* Stop listening to mousemove event
* @private
* @return {void}
*/
removeDocumentMouseMoveListener() {
this.node.ownerDocument.removeEventListener('mousemove', this.handleMouseMove);
}

/**
* Stop listening to touchend event
* @private
Expand All @@ -337,7 +380,7 @@ export default class InputRange extends React.Component {
}

/**
* Handle any "mousemove" event received by the slider
* Handle drag "mousemove" event received by the slider
* @private
* @param {SyntheticEvent} event
* @param {string} key
Expand All @@ -354,6 +397,92 @@ export default class InputRange extends React.Component {
requestAnimationFrame(() => this.updatePosition(key, position));
}

/**
* Handle any non-drag "mousemove" event received by the slider
* @private
* @param {SyntheticEvent} event
* @param {string} key
* @return {void}
*/
@autobind
handleMouseMove(event) {
if (this.props.disabled) {
return;
}

const position = valueTransformer.getPositionFromEvent(event, this.getTrackClientRect());

const value = valueTransformer.getValueFromPosition(position, this.props.minValue, this.props.maxValue, this.getTrackClientRect());

console.log('MouseMove Position: ', position);
console.log('MouseMove Values: ', value);

// TODO: Add CSS to label and remove console.log
// Set top and left based on event.pageX and event.pageY?

this.setState({
hoverValue: value,
});
}

/**
* Handle any "mouseover" event received by the slider
* @private
* @param {SyntheticEvent} event
* @param {string} key
* @return {void}
*/
@autobind
handleMouseOver(event) {
if (this.props.disabled) {
return;
}

const position = valueTransformer.getPositionFromEvent(event, this.getTrackClientRect());

const value = valueTransformer.getValueFromPosition(position, this.props.minValue, this.props.maxValue, this.getTrackClientRect());

console.log('MouseOver Position: ', position);
console.log('MouseOver Value: ', value);

// TODO: Add CSS to hoverLabel and remove console.log
// Set top and left based on event.pageX and event.pageY?

this.setState({
hovering: true,
hoverValue: value,
});
}


/**
* Handle any "mouseout" event received by the slider
* @private
* @param {SyntheticEvent} event
* @param {string} key
* @return {void}
*/
@autobind
handleMouseOut(event) {
if (this.props.disabled) {
return;
}

const position = valueTransformer.getPositionFromEvent(event, this.getTrackClientRect());
const value = valueTransformer.getValueFromPosition(position, this.props.minValue, this.props.maxValue, this.getTrackClientRect());

console.log('MouseOut Position: ', position);
console.log('MouseOut Value: ', value);

// TODO: Remove CSS from hoverLabel and remove console.log

this.setState({
hovering: false,
hoverValue: value,
});
}


/**
* Handle any "keydown" event received by the slider
* @private
Expand Down Expand Up @@ -535,6 +664,9 @@ export default class InputRange extends React.Component {
minValue={minValue}
onSliderDrag={this.handleSliderDrag}
onSliderKeyDown={this.handleSliderKeyDown}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
onMouseMove={this.handleMouseMove}
percentage={percentage}
type={key}
value={value} />
Expand Down Expand Up @@ -597,9 +729,23 @@ export default class InputRange extends React.Component {
classNames={this.props.classNames}
ref={(trackNode) => { this.trackNode = trackNode; }}
percentages={percentages}
onTrackMouseDown={this.handleTrackMouseDown}>
onTrackMouseDown={this.handleTrackMouseDown}
onTrackMouseOver={this.handleMouseOver}
onTrackMouseOut={this.handleMouseOut}
onTrackMouseMove={this.handleMouseMove} >

{this.renderSliders()}
{
this.props.showHoverLabel && this.state.hovering &&
<Label
ref={(node) => { this.hoverLabel = node; }}
classNames={this.props.classNames}
formatLabel={this.props.formatLabel}
type="hover">
{this.state.hoverValue}
</Label>

}
</Track>

<Label
Expand Down
2 changes: 2 additions & 0 deletions src/js/input-range/slider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export default class Slider extends React.Component {
componentWillUnmount() {
this.removeDocumentMouseMoveListener();
this.removeDocumentMouseUpListener();
this.removeDocumentMouseOverListener();
this.removeDocumentMouseOutListener();
this.removeDocumentTouchEndListener();
this.removeDocumentTouchMoveListener();
}
Expand Down
64 changes: 64 additions & 0 deletions src/js/input-range/track.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ export default class Track extends React.Component {
* @property {Function} children
* @property {Function} classNames
* @property {Function} onTrackMouseDown
* @property {Function} onTrackMouseOver
* @property {Function} onTrackMouseOut
* @property {Function} onTrackMouseMove
* @property {Function} percentages
*/
static get propTypes() {
return {
children: React.PropTypes.node.isRequired,
classNames: React.PropTypes.objectOf(React.PropTypes.string).isRequired,
onTrackMouseDown: React.PropTypes.func.isRequired,
onTrackMouseOver: React.PropTypes.func.isRequired,
onTrackMouseOut: React.PropTypes.func.isRequired,
onTrackMouseMove: React.PropTypes.func.isRequired,
percentages: React.PropTypes.objectOf(React.PropTypes.number).isRequired,
};
}
Expand All @@ -26,6 +32,9 @@ export default class Track extends React.Component {
* @param {Object} props
* @param {InputRangeClassNames} props.classNames
* @param {Function} props.onTrackMouseDown
* @param {Function} props.onTrackMouseOver
* @param {Function} props.onTrackMouseOut
* @param {Function} props.onTrackMouseMove
* @param {number} props.percentages
*/
constructor(props) {
Expand Down Expand Up @@ -84,6 +93,58 @@ export default class Track extends React.Component {
this.handleMouseDown(event);
}


/**
* @private
* @param {SyntheticEvent} event
* @return {void}
*/
@autobind
handleMouseMove(event) {
const clientX = event.touches ? event.touches[0].clientX : event.clientX;
const trackClientRect = this.getClientRect();
const position = {
x: clientX - trackClientRect.left,
y: 0,
};

this.props.onTrackMouseMove(event, position);
}

/**
* @private
* @param {SyntheticEvent} event
* @return {void}
*/
@autobind
handleMouseOver(event) {
const clientX = event.touches ? event.touches[0].clientX : event.clientX;
const trackClientRect = this.getClientRect();
const position = {
x: clientX - trackClientRect.left,
y: 0,
};

this.props.onTrackMouseOver(event, position);
}

/**
* @private
* @param {SyntheticEvent} event
* @return {void}
*/
@autobind
handleMouseOut(event) {
const clientX = event.touches ? event.touches[0].clientX : event.clientX;
const trackClientRect = this.getClientRect();
const position = {
x: clientX - trackClientRect.left,
y: 0,
};

this.props.onTrackMouseOut(event, position);
}

/**
* @override
* @return {JSX.Element}
Expand All @@ -96,6 +157,9 @@ export default class Track extends React.Component {
className={this.props.classNames.track}
onMouseDown={this.handleMouseDown}
onTouchStart={this.handleTouchStart}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
onMouseMove={this.handleMouseMove}
ref={(node) => { this.node = node; }}>
<div
style={activeTrackStyle}
Expand Down