Created
May 8, 2021 21:25
-
-
Save Spencer-Doak/9954daae8a859337a08f0022293313a6 to your computer and use it in GitHub Desktop.
Recursively find all shadow roots in a page.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Recursive depth-first search to find all shadow roots within a webpage. | |
* | |
* Example usage: let's imagine you come across a page that has a bunch of | |
* expandable information sections, and you would like to expand all of those | |
* info sections for the sake of printing to a PDF or for the ease of | |
* performing a simple `CTRL+F` search across the information. Let's assume | |
* those expanding buttons are buried within Shadow DOM. (Perhaps the site is | |
* using Angular or something of the sort & the buttons are separate | |
* components, thus by default they end up in a Shadow DOM whenever included.) | |
* Of course, you're not going click 30 different buttons like some mortal, but | |
* Shadow DOM prevents you from simply saying: | |
* `document.body.querySelectorAll('button.btn-expand-more-details')` | |
* | |
* This is where the `findRoots` function can help you out. Instead of | |
* resorting to clicking each button by hand, you can "Search in the Shadows" | |
* by leveraging the `findRoots(...)` function to locate all shadow document | |
* fragments. You can then execute `querySelectorAll('...')` across all | |
* document fragments to locate the buttons you want to click. Your code might | |
* read: | |
* | |
* ```javascript | |
* [ | |
* document.body, | |
* ...findRoots(document.body) | |
* ].flatMap( | |
* e=>e.querySelectorAll('button.btn-expand-more-details') | |
* ).forEach(e=>e.click()) | |
* ``` | |
* | |
* @param {Node} ele - An element that we should search for ShadowRoots within. | |
* @returns {Array<ShadowRoot>} Array of ShadowRoots found below/contained | |
* within the given node, `ele`. | |
*/ | |
function findRoots(ele) { | |
return [ | |
ele, | |
...ele.querySelectorAll('*') | |
].filter(e => !!e.shadowRoot) | |
.flatMap(e => [e.shadowRoot, ...findRoots(e.shadowRoot)]) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment