Skip to content

Commit 2839d96

Browse files
committed
Fill fields inside shadow roots
1 parent f4fffcd commit 2839d96

1 file changed

Lines changed: 70 additions & 52 deletions

File tree

src/inject.js

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,20 @@
270270
return result;
271271
}
272272

273+
/**
274+
* Get list of shadow DOM roots, recursively.
275+
*
276+
* @since 3.12.0
277+
*
278+
* @param DOMElement parent Parent element to query
279+
* @return array List of shadow root elements plus parent
280+
*/
281+
function queryShadowRoots(parent) {
282+
return [parent, ...parent.querySelectorAll("*")]
283+
.filter((e) => e.shadowRoot)
284+
.flatMap((e) => [e.shadowRoot, ...queryShadowRoots(e.shadowRoot)]);
285+
}
286+
273287
/**
274288
* Query all visible elements
275289
*
@@ -282,60 +296,64 @@
282296
*/
283297
function queryAllVisible(parent, field, form) {
284298
const result = [];
285-
for (let i = 0; i < field.selectors.length; i++) {
286-
let elems = parent.querySelectorAll(field.selectors[i]);
287-
for (let j = 0; j < elems.length; j++) {
288-
let elem = elems[j];
289-
// Select only elements from specified form
290-
if (form && form != elem.form) {
291-
continue;
292-
}
293-
// Ignore disabled fields
294-
if (elem.disabled) {
295-
continue;
296-
}
297-
// Elem or its parent has a style 'display: none',
298-
// or it is just too narrow to be a real field (a trap for spammers?).
299-
if (elem.offsetWidth < 30 || elem.offsetHeight < 10) {
300-
continue;
301-
}
302-
// We may have a whitelist of acceptable field types. If so, skip elements of a different type.
303-
if (field.types && field.types.indexOf(elem.type.toLowerCase()) < 0) {
304-
continue;
305-
}
306-
// Elem takes space on the screen, but it or its parent is hidden with a visibility style.
307-
let style = window.getComputedStyle(elem);
308-
if (style.visibility == "hidden") {
309-
continue;
310-
}
311-
// Elem is outside of the boundaries of the visible viewport.
312-
let rect = elem.getBoundingClientRect();
313-
if (
314-
rect.x + rect.width < 0 ||
315-
rect.y + rect.height < 0 ||
316-
rect.x > window.innerWidth ||
317-
rect.y > window.innerHeight
318-
) {
319-
continue;
320-
}
321-
// Elem is hidden by its or or its parent's opacity rules
322-
const OPACITY_LIMIT = 0.1;
323-
let opacity = 1;
324-
for (
325-
let testElem = elem;
326-
opacity >= OPACITY_LIMIT && testElem && testElem.nodeType === Node.ELEMENT_NODE;
327-
testElem = testElem.parentNode
328-
) {
329-
let style = window.getComputedStyle(testElem);
330-
if (style.opacity) {
331-
opacity *= parseFloat(style.opacity);
299+
for (let root of queryShadowRoots(parent)) {
300+
for (let i = 0; i < field.selectors.length; i++) {
301+
let elems = root.querySelectorAll(field.selectors[i]);
302+
for (let j = 0; j < elems.length; j++) {
303+
let elem = elems[j];
304+
// Select only elements from specified form
305+
if (form && form != elem.form) {
306+
continue;
332307
}
308+
// Ignore disabled fields
309+
if (elem.disabled) {
310+
continue;
311+
}
312+
// Elem or its parent has a style 'display: none',
313+
// or it is just too narrow to be a real field (a trap for spammers?).
314+
if (elem.offsetWidth < 30 || elem.offsetHeight < 10) {
315+
continue;
316+
}
317+
// We may have a whitelist of acceptable field types. If so, skip elements of a different type.
318+
if (field.types && field.types.indexOf(elem.type.toLowerCase()) < 0) {
319+
continue;
320+
}
321+
// Elem takes space on the screen, but it or its parent is hidden with a visibility style.
322+
let style = window.getComputedStyle(elem);
323+
if (style.visibility == "hidden") {
324+
continue;
325+
}
326+
// Elem is outside of the boundaries of the visible viewport.
327+
let rect = elem.getBoundingClientRect();
328+
if (
329+
rect.x + rect.width < 0 ||
330+
rect.y + rect.height < 0 ||
331+
rect.x > window.innerWidth ||
332+
rect.y > window.innerHeight
333+
) {
334+
continue;
335+
}
336+
// Elem is hidden by its or or its parent's opacity rules
337+
const OPACITY_LIMIT = 0.1;
338+
let opacity = 1;
339+
for (
340+
let testElem = elem;
341+
opacity >= OPACITY_LIMIT &&
342+
testElem &&
343+
testElem.nodeType === Node.ELEMENT_NODE;
344+
testElem = testElem.parentNode
345+
) {
346+
let style = window.getComputedStyle(testElem);
347+
if (style.opacity) {
348+
opacity *= parseFloat(style.opacity);
349+
}
350+
}
351+
if (opacity < OPACITY_LIMIT) {
352+
continue;
353+
}
354+
// This element is visible, will use it.
355+
result.push(elem);
333356
}
334-
if (opacity < OPACITY_LIMIT) {
335-
continue;
336-
}
337-
// This element is visible, will use it.
338-
result.push(elem);
339357
}
340358
}
341359
return result;

0 commit comments

Comments
 (0)