0

As the title says, how do I get all elements including open shadowRoot elements and their children, which might also contain open shadowRoot elements?

I've found a few similar questions on SO, but they all return (inner|outer)HTML, which is similar but also very different logic. I want to return an object or array with the shadowRoot elements included.

I don't mind switching from getElementsByTagName("*") to querySelectorAll("*") if it makes things easier, but I don't think it will.

Edit

I don't think it's possible to accomplish what I want here, e.g. return an object/array of all elements on the page including nested shadowRoot elements. Again, my end goal is to getComputedStyle() on every element on the page, including shadowRoot nodes.

The only thing I can think of to accomplish this would be to use a function similar to this on SO or this on SO to get all the HTML, add it to the page somewhere hidden, parse it, then optionally remove it from the page.

Any suggestions or ideas are appreciated.

Jeff
  • 5,962
  • 16
  • 49
  • 81
  • 1
    Since shadow roots are intended to encapsulate the contents of custom elements, I’m struggling to understand, why you’d ever need this. It is theoretically possible with open shadow roots using code like this: `const allElems = (root) => Array.from(root.querySelectorAll("*")).flatMap((elem) => (elem.shadowRoot ? [ elem, ...allElems(elem.shadowRoot) ] : [ elem ])); allElems(document);`. – Sebastian Simon Oct 23 '22 at 19:24
  • I need to `getComputedStyle()` on the nodes in the shadowRoot. – Jeff Oct 23 '22 at 19:26

1 Answers1

-1

Just use recursion to loop thru the whole document?

function walkTree(node) {
  if (node === null) {
    return;
  }
  // do something with node
  for (let i = 0; i < node.childNodes.length; i++) {
    walkTree(node.childNodes[i]);
  }
}

A use case would be something like:

function walkTree(node) {
  if (node === null) {
    return;
  }
  // do something with node
  for (let i = 0; i < node.childNodes.length; i++) {
    if(node.childNodes[i].tagName){
      console.log(node.childNodes[i].tagName);
    }
    walkTree(node.childNodes[i]);
  }
}
document.getElementById("rt").attachShadow({mode: 'closed'});
var doc = document.getElementsByTagName("HTML")[0]
walkTree(doc);
<html>
    <head>
        <title>This is <span>the title</span></title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    </head>
    <body class="my-class">
        <main>
          <h1>This is a header</h1>
          <div>
            <div class="something">
              <p>This is a <span>paragraph</span></p>
            </div>
            <div id="shadow-rt">
                <div>
                    <span id="shadow-dom-child"></span>
                </div>
            </div>
          </div>
        </main>
    </body>
</html>
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
  • I think this is the start of the right answer, but I'm not good enough with js to understand how to include the `.shadowRoot` nodes recursively and build an array/object. – Jeff Oct 23 '22 at 20:46