UNPKG

4.58 kBJavaScriptView Raw
1import Set from '../set';
2import cache from './cache-traversal-call';
3
4let elesfn = ({
5 parent: function( selector ){
6 let parents = [];
7
8 // optimisation for single ele call
9 if( this.length === 1 ){
10 let parent = this[0]._private.parent;
11
12 if( parent ){ return parent; }
13 }
14
15 for( let i = 0; i < this.length; i++ ){
16 let ele = this[ i ];
17 let parent = ele._private.parent;
18
19 if( parent ){
20 parents.push( parent );
21 }
22 }
23
24 return this.spawn( parents, true ).filter( selector );
25 },
26
27 parents: function( selector ){
28 let parents = [];
29
30 let eles = this.parent();
31 while( eles.nonempty() ){
32 for( let i = 0; i < eles.length; i++ ){
33 let ele = eles[ i ];
34 parents.push( ele );
35 }
36
37 eles = eles.parent();
38 }
39
40 return this.spawn( parents, true ).filter( selector );
41 },
42
43 commonAncestors: function( selector ){
44 let ancestors;
45
46 for( let i = 0; i < this.length; i++ ){
47 let ele = this[ i ];
48 let parents = ele.parents();
49
50 ancestors = ancestors || parents;
51
52 ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set
53 }
54
55 return ancestors.filter( selector );
56 },
57
58 orphans: function( selector ){
59 return this.stdFilter( function( ele ){
60 return ele.isOrphan();
61 } ).filter( selector );
62 },
63
64 nonorphans: function( selector ){
65 return this.stdFilter( function( ele ){
66 return ele.isChild();
67 } ).filter( selector );
68 },
69
70 children: cache( function( selector ){
71 let children = [];
72
73 for( let i = 0; i < this.length; i++ ){
74 let ele = this[ i ];
75 let eleChildren = ele._private.children;
76
77 for( let j = 0; j < eleChildren.length; j++ ){
78 children.push( eleChildren[j] );
79 }
80 }
81
82 return this.spawn( children, true ).filter( selector );
83 }, 'children' ),
84
85 siblings: function( selector ){
86 return this.parent().children().not( this ).filter( selector );
87 },
88
89 isParent: function(){
90 let ele = this[0];
91
92 if( ele ){
93 return ele.isNode() && ele._private.children.length !== 0;
94 }
95 },
96
97 isChildless: function(){
98 let ele = this[0];
99
100 if( ele ){
101 return ele.isNode() && ele._private.children.length === 0;
102 }
103 },
104
105 isChild: function(){
106 let ele = this[0];
107
108 if( ele ){
109 return ele.isNode() && ele._private.parent != null;
110 }
111 },
112
113 isOrphan: function(){
114 let ele = this[0];
115
116 if( ele ){
117 return ele.isNode() && ele._private.parent == null;
118 }
119 },
120
121 descendants: function( selector ){
122 let elements = [];
123
124 function add( eles ){
125 for( let i = 0; i < eles.length; i++ ){
126 let ele = eles[ i ];
127
128 elements.push( ele );
129
130 if( ele.children().nonempty() ){
131 add( ele.children() );
132 }
133 }
134 }
135
136 add( this.children() );
137
138 return this.spawn( elements, true ).filter( selector );
139 }
140});
141
142function forEachCompound( eles, fn, includeSelf, recursiveStep ){
143 let q = [];
144 let did = new Set();
145 let cy = eles.cy();
146 let hasCompounds = cy.hasCompoundNodes();
147
148 for( let i = 0; i < eles.length; i++ ){
149 let ele = eles[i];
150
151 if( includeSelf ){
152 q.push( ele );
153 } else if( hasCompounds ){
154 recursiveStep( q, did, ele );
155 }
156 }
157
158 while( q.length > 0 ){
159 let ele = q.shift();
160
161 fn( ele );
162
163 did.add( ele.id() );
164
165 if( hasCompounds ){
166 recursiveStep( q, did, ele );
167 }
168 }
169
170 return eles;
171}
172
173function addChildren( q, did, ele ){
174 if( ele.isParent() ){
175 let children = ele._private.children;
176
177 for( let i = 0; i < children.length; i++ ){
178 let child = children[i];
179
180 if( !did.has( child.id() ) ){
181 q.push( child );
182 }
183 }
184 }
185}
186
187// very efficient version of eles.add( eles.descendants() ).forEach()
188// for internal use
189elesfn.forEachDown = function( fn, includeSelf = true ){
190 return forEachCompound( this, fn, includeSelf, addChildren );
191};
192
193function addParent( q, did, ele ){
194 if( ele.isChild() ){
195 let parent = ele._private.parent;
196
197 if( !did.has( parent.id() ) ){
198 q.push( parent );
199 }
200 }
201}
202
203elesfn.forEachUp = function( fn, includeSelf = true ){
204 return forEachCompound( this, fn, includeSelf, addParent );
205};
206
207function addParentAndChildren( q, did, ele ){
208 addParent( q, did, ele );
209 addChildren( q, did, ele );
210}
211
212elesfn.forEachUpAndDown = function( fn, includeSelf = true ){
213 return forEachCompound( this, fn, includeSelf, addParentAndChildren );
214};
215
216// aliases
217elesfn.ancestors = elesfn.parents;
218
219export default elesfn;