97 lines
3.1 KiB
JavaScript
97 lines
3.1 KiB
JavaScript
|
/**
|
||
|
* Copyright 2013-present, Facebook, Inc.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This source code is licensed under the BSD-style license found in the
|
||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
var EventPropagators = require('./EventPropagators');
|
||
|
var ReactDOMComponentTree = require('./ReactDOMComponentTree');
|
||
|
var SyntheticMouseEvent = require('./SyntheticMouseEvent');
|
||
|
|
||
|
var eventTypes = {
|
||
|
mouseEnter: {
|
||
|
registrationName: 'onMouseEnter',
|
||
|
dependencies: ['topMouseOut', 'topMouseOver']
|
||
|
},
|
||
|
mouseLeave: {
|
||
|
registrationName: 'onMouseLeave',
|
||
|
dependencies: ['topMouseOut', 'topMouseOver']
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var EnterLeaveEventPlugin = {
|
||
|
eventTypes: eventTypes,
|
||
|
|
||
|
/**
|
||
|
* For almost every interaction we care about, there will be both a top-level
|
||
|
* `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
|
||
|
* we do not extract duplicate events. However, moving the mouse into the
|
||
|
* browser from outside will not fire a `mouseout` event. In this case, we use
|
||
|
* the `mouseover` top-level event.
|
||
|
*/
|
||
|
extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
|
||
|
if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
|
||
|
return null;
|
||
|
}
|
||
|
if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
|
||
|
// Must not be a mouse in or mouse out - ignoring.
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
var win;
|
||
|
if (nativeEventTarget.window === nativeEventTarget) {
|
||
|
// `nativeEventTarget` is probably a window object.
|
||
|
win = nativeEventTarget;
|
||
|
} else {
|
||
|
// TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
|
||
|
var doc = nativeEventTarget.ownerDocument;
|
||
|
if (doc) {
|
||
|
win = doc.defaultView || doc.parentWindow;
|
||
|
} else {
|
||
|
win = window;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var from;
|
||
|
var to;
|
||
|
if (topLevelType === 'topMouseOut') {
|
||
|
from = targetInst;
|
||
|
var related = nativeEvent.relatedTarget || nativeEvent.toElement;
|
||
|
to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;
|
||
|
} else {
|
||
|
// Moving to a node from outside the window.
|
||
|
from = null;
|
||
|
to = targetInst;
|
||
|
}
|
||
|
|
||
|
if (from === to) {
|
||
|
// Nothing pertains to our managed components.
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);
|
||
|
var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);
|
||
|
|
||
|
var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);
|
||
|
leave.type = 'mouseleave';
|
||
|
leave.target = fromNode;
|
||
|
leave.relatedTarget = toNode;
|
||
|
|
||
|
var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);
|
||
|
enter.type = 'mouseenter';
|
||
|
enter.target = toNode;
|
||
|
enter.relatedTarget = fromNode;
|
||
|
|
||
|
EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);
|
||
|
|
||
|
return [leave, enter];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
module.exports = EnterLeaveEventPlugin;
|