UNPKG

3.03 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9'use strict';
10
11var EventPropagators = require('./EventPropagators');
12var ReactDOMComponentTree = require('./ReactDOMComponentTree');
13var SyntheticMouseEvent = require('./SyntheticMouseEvent');
14
15var eventTypes = {
16 mouseEnter: {
17 registrationName: 'onMouseEnter',
18 dependencies: ['topMouseOut', 'topMouseOver']
19 },
20 mouseLeave: {
21 registrationName: 'onMouseLeave',
22 dependencies: ['topMouseOut', 'topMouseOver']
23 }
24};
25
26var EnterLeaveEventPlugin = {
27 eventTypes: eventTypes,
28
29 /**
30 * For almost every interaction we care about, there will be both a top-level
31 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
32 * we do not extract duplicate events. However, moving the mouse into the
33 * browser from outside will not fire a `mouseout` event. In this case, we use
34 * the `mouseover` top-level event.
35 */
36 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
37 if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
38 return null;
39 }
40 if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
41 // Must not be a mouse in or mouse out - ignoring.
42 return null;
43 }
44
45 var win;
46 if (nativeEventTarget.window === nativeEventTarget) {
47 // `nativeEventTarget` is probably a window object.
48 win = nativeEventTarget;
49 } else {
50 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
51 var doc = nativeEventTarget.ownerDocument;
52 if (doc) {
53 win = doc.defaultView || doc.parentWindow;
54 } else {
55 win = window;
56 }
57 }
58
59 var from;
60 var to;
61 if (topLevelType === 'topMouseOut') {
62 from = targetInst;
63 var related = nativeEvent.relatedTarget || nativeEvent.toElement;
64 to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;
65 } else {
66 // Moving to a node from outside the window.
67 from = null;
68 to = targetInst;
69 }
70
71 if (from === to) {
72 // Nothing pertains to our managed components.
73 return null;
74 }
75
76 var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);
77 var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);
78
79 var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);
80 leave.type = 'mouseleave';
81 leave.target = fromNode;
82 leave.relatedTarget = toNode;
83
84 var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);
85 enter.type = 'mouseenter';
86 enter.target = toNode;
87 enter.relatedTarget = fromNode;
88
89 EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);
90
91 return [leave, enter];
92 }
93};
94
95module.exports = EnterLeaveEventPlugin;
\No newline at end of file