UNPKG

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