UNPKG

3.6 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015-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 _prodInvariant = require('./reactProdInvariant');
12
13var invariant = require('fbjs/lib/invariant');
14
15/**
16 * Return the lowest common ancestor of A and B, or null if they are in
17 * different trees.
18 */
19function getLowestCommonAncestor(instA, instB) {
20 !('_hostNode' in instA) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;
21 !('_hostNode' in instB) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;
22
23 var depthA = 0;
24 for (var tempA = instA; tempA; tempA = tempA._hostParent) {
25 depthA++;
26 }
27 var depthB = 0;
28 for (var tempB = instB; tempB; tempB = tempB._hostParent) {
29 depthB++;
30 }
31
32 // If A is deeper, crawl up.
33 while (depthA - depthB > 0) {
34 instA = instA._hostParent;
35 depthA--;
36 }
37
38 // If B is deeper, crawl up.
39 while (depthB - depthA > 0) {
40 instB = instB._hostParent;
41 depthB--;
42 }
43
44 // Walk in lockstep until we find a match.
45 var depth = depthA;
46 while (depth--) {
47 if (instA === instB) {
48 return instA;
49 }
50 instA = instA._hostParent;
51 instB = instB._hostParent;
52 }
53 return null;
54}
55
56/**
57 * Return if A is an ancestor of B.
58 */
59function isAncestor(instA, instB) {
60 !('_hostNode' in instA) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;
61 !('_hostNode' in instB) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;
62
63 while (instB) {
64 if (instB === instA) {
65 return true;
66 }
67 instB = instB._hostParent;
68 }
69 return false;
70}
71
72/**
73 * Return the parent instance of the passed-in instance.
74 */
75function getParentInstance(inst) {
76 !('_hostNode' in inst) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;
77
78 return inst._hostParent;
79}
80
81/**
82 * Simulates the traversal of a two-phase, capture/bubble event dispatch.
83 */
84function traverseTwoPhase(inst, fn, arg) {
85 var path = [];
86 while (inst) {
87 path.push(inst);
88 inst = inst._hostParent;
89 }
90 var i;
91 for (i = path.length; i-- > 0;) {
92 fn(path[i], 'captured', arg);
93 }
94 for (i = 0; i < path.length; i++) {
95 fn(path[i], 'bubbled', arg);
96 }
97}
98
99/**
100 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
101 * should would receive a `mouseEnter` or `mouseLeave` event.
102 *
103 * Does not invoke the callback on the nearest common ancestor because nothing
104 * "entered" or "left" that element.
105 */
106function traverseEnterLeave(from, to, fn, argFrom, argTo) {
107 var common = from && to ? getLowestCommonAncestor(from, to) : null;
108 var pathFrom = [];
109 while (from && from !== common) {
110 pathFrom.push(from);
111 from = from._hostParent;
112 }
113 var pathTo = [];
114 while (to && to !== common) {
115 pathTo.push(to);
116 to = to._hostParent;
117 }
118 var i;
119 for (i = 0; i < pathFrom.length; i++) {
120 fn(pathFrom[i], 'bubbled', argFrom);
121 }
122 for (i = pathTo.length; i-- > 0;) {
123 fn(pathTo[i], 'captured', argTo);
124 }
125}
126
127module.exports = {
128 isAncestor: isAncestor,
129 getLowestCommonAncestor: getLowestCommonAncestor,
130 getParentInstance: getParentInstance,
131 traverseTwoPhase: traverseTwoPhase,
132 traverseEnterLeave: traverseEnterLeave
133};
\No newline at end of file