Skip to content

Instantly share code, notes, and snippets.

@petehunt
Last active December 18, 2015 22:39
Show Gist options
  • Save petehunt/c2a1aa6bb30cb4699bd8 to your computer and use it in GitHub Desktop.
Save petehunt/c2a1aa6bb30cb4699bd8 to your computer and use it in GitHub Desktop.
'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