'use strict'; | |
var React = require('react'); | |
var emptyFunction = require('../../jslib/emptyFunction'); | |
var throttle = require('lodash.throttle'); | |
var listening = false; | |
var instances = []; | |
function onMouseMove(e) { | |
// Get the containing react element ID | |
var target = e.target; | |
var reactID = null; | |
while (target && !reactID) { | |
// TODO: use react internals | |
if (target.nodeType === 1) { | |
reactID = target.dataset.reactid; | |
} | |
target = target.parentNode; | |
} | |
if (!reactID) { | |
return; | |
} | |
instances.forEach(function(instance) { | |
instance.checkHover(reactID); | |
}); | |
} | |
var HoverRegion = React.createClass({ | |
getDefaultProps: function() { | |
return { | |
onMouseEnter: emptyFunction, | |
onMouseLeave: emptyFunction, | |
onHoverChange: emptyFunction, | |
}; | |
}, | |
render: function() { | |
return ( | |
<div style={this.props.style}>{this.props.children}</div> | |
); | |
}, | |
componentDidMount: function() { | |
if (!listening) { | |
window.addEventListener( | |
'mousemove', | |
onMouseMove, | |
false | |
); | |
listening = true; | |
} | |
this.hovered = false; | |
this._updateCheckHover(); | |
instances.push(this); | |
}, | |
componentWillUnmount: function() { | |
this.checkHover.cancel(); | |
instances.splice(instances.indexOf(this), 1); | |
}, | |
componentDidUpdate: function(prevProps) { | |
if (this.props.throttle !== prevProps.throttle) { | |
this._updateCheckHover(); | |
} | |
}, | |
isHovered: function() { | |
return this.hovered; | |
}, | |
_updateCheckHover: function() { | |
if (this.checkHover) { | |
this.checkHover.cancel(); | |
this._checkHover(); | |
} | |
this.checkHover = throttle(this._checkHover, this.props.throttle); | |
}, | |
_checkHover: function(reactID) { | |
// TODO: use react internals | |
var myReactID = this._reactInternalInstance._rootNodeID; | |
if (myReactID.length > reactID.length) { | |
this._setHovered(false); | |
} else if (myReactID.length === reactID.length) { | |
this._setHovered(myReactID === reactID); | |
} else { | |
this._setHovered(reactID.slice(0, myReactID.length) === myReactID); | |
} | |
}, | |
_setHovered: function(hovered) { | |
if (this.hovered !== hovered) { | |
this.hovered = hovered; | |
this.props.onHoverChange(hovered); | |
if (hovered) { | |
this.props.onMouseEnter(); | |
} else { | |
this.props.onMouseLeave(); | |
} | |
} | |
}, | |
}); | |
module.exports = HoverRegion; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment