17
17
* Another example querySelectorAllDeep('#downloads-list div#title-area + a');
18
18
e.g.
19
19
*/
20
- export function querySelectorAllDeep ( selector , root = document ) {
21
- return _querySelectorDeep ( selector , true , root ) ;
20
+ export function querySelectorAllDeep ( selector , root = document , allElements = null ) {
21
+ return _querySelectorDeep ( selector , true , root , allElements ) ;
22
22
}
23
23
24
- export function querySelectorDeep ( selector , root = document ) {
25
- return _querySelectorDeep ( selector , false , root ) ;
24
+ export function querySelectorDeep ( selector , root = document , allElements = null ) {
25
+ return _querySelectorDeep ( selector , false , root , allElements ) ;
26
26
}
27
27
28
- function _querySelectorDeep ( selector , findMany , root ) {
28
+ function _querySelectorDeep ( selector , findMany , root , allElements = null ) {
29
29
selector = normalizeSelector ( selector )
30
30
let lightElement = root . querySelector ( selector ) ;
31
31
@@ -48,10 +48,14 @@ function _querySelectorDeep(selector, findMany, root) {
48
48
//remove white space at start of selector
49
49
. replace ( / ^ \s + / g, '' )
50
50
. replace ( / \s * ( [ > + ~ ] + ) \s * / g, '$1' ) , ' ' )
51
- // filter out entry white selectors
52
- . filter ( ( entry ) => ! ! entry ) ;
51
+ // filter out entry white selectors
52
+ . filter ( ( entry ) => ! ! entry )
53
+ // convert "a > b" to ["a", "b"]
54
+ . map ( ( entry ) => splitByCharacterUnlessQuoted ( entry , '>' ) ) ;
55
+
53
56
const possibleElementsIndex = splitSelector . length - 1 ;
54
- const possibleElements = collectAllElementsDeep ( splitSelector [ possibleElementsIndex ] , root ) ;
57
+ const lastSplitPart = splitSelector [ possibleElementsIndex ] [ splitSelector [ possibleElementsIndex ] . length - 1 ]
58
+ const possibleElements = collectAllElementsDeep ( lastSplitPart , root , allElements ) ;
55
59
const findElements = findMatchingElement ( splitSelector , possibleElementsIndex , root ) ;
56
60
if ( findMany ) {
57
61
acc = acc . concat ( possibleElements . filter ( findElements ) ) ;
@@ -79,7 +83,23 @@ function findMatchingElement(splitSelector, possibleElementsIndex, root) {
79
83
let parent = element ;
80
84
let foundElement = false ;
81
85
while ( parent && ! isDocumentNode ( parent ) ) {
82
- const foundMatch = parent . matches ( splitSelector [ position ] ) ;
86
+ let foundMatch = true
87
+ if ( splitSelector [ position ] . length === 1 ) {
88
+ foundMatch = parent . matches ( splitSelector [ position ] ) ;
89
+ } else {
90
+ // selector is in the format "a > b"
91
+ // make sure a few parents match in order
92
+ const reversedParts = ( [ ] ) . concat ( splitSelector [ position ] ) . reverse ( )
93
+ let newParent = parent
94
+ for ( const part of reversedParts ) {
95
+ if ( ! newParent || ! newParent . matches ( part ) ) {
96
+ foundMatch = false
97
+ break
98
+ }
99
+ newParent = findParentOrHost ( newParent , root ) ;
100
+ }
101
+ }
102
+
83
103
if ( foundMatch && position === 0 ) {
84
104
foundElement = true ;
85
105
break ;
@@ -133,27 +153,30 @@ function findParentOrHost(element, root) {
133
153
* @author ebidel@ (Eric Bidelman)
134
154
* License Apache-2.0
135
155
*/
136
- function collectAllElementsDeep ( selector = null , root ) {
137
- const allElements = [ ] ;
138
-
139
- const findAllElements = function ( nodes ) {
140
- for ( let i = 0 , el ; el = nodes [ i ] ; ++ i ) {
141
- allElements . push ( el ) ;
142
- // If the element has a shadow root, dig deeper.
143
- if ( el . shadowRoot ) {
144
- findAllElements ( el . shadowRoot . querySelectorAll ( '*' ) ) ;
156
+ export function collectAllElementsDeep ( selector = null , root , cachedElements = null ) {
157
+ let allElements = [ ] ;
158
+
159
+ if ( cachedElements ) {
160
+ allElements = cachedElements ;
161
+ } else {
162
+ const findAllElements = function ( nodes ) {
163
+ for ( let i = 0 , el ; el = nodes [ i ] ; ++ i ) {
164
+ allElements . push ( el ) ;
165
+ // If the element has a shadow root, dig deeper.
166
+ if ( el . shadowRoot ) {
167
+ findAllElements ( el . shadowRoot . querySelectorAll ( '*' ) ) ;
168
+ }
145
169
}
146
170
}
147
- } ;
148
- if ( root . shadowRoot ) {
149
- findAllElements ( root . shadowRoot . querySelectorAll ( '*' ) ) ;
171
+ if ( root . shadowRoot ) {
172
+ findAllElements ( root . shadowRoot . querySelectorAll ( '*' ) ) ;
173
+ }
174
+ findAllElements ( root . querySelectorAll ( '*' ) ) ;
150
175
}
151
- findAllElements ( root . querySelectorAll ( '*' ) ) ;
152
176
153
177
return allElements . filter ( el => el . matches ( selector ) ) ;
154
178
}
155
179
156
-
157
180
// normalize-selector-rev-02.js
158
181
/*
159
182
author: kyle simpson (@getify)
0 commit comments