10

How can I get all descendant Elements for parent container? I want to get them in array.

<div class="parent">
    <div class="child1">
        <span class="child2">
            <div class="child3">
                <div class="child4">
                    <span class="child5"></span>
                </div>
                <div class="child6">
                    <div class="class7"></div>
                </div>
            </div>
        </span>

        <div class="child8"></div>
        <span class="child9">
            <div class="child10"></div>
        </span>
    </div>
</div>

I'm think about recursion as one of options. At the first point I know parent Element.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Alex
  • 2,091
  • 6
  • 31
  • 49
  • possible duplicate of [How to get all elements inside "div" that starts with a known text](http://stackoverflow.com/questions/2617629/how-to-get-all-elements-inside-div-that-starts-with-a-known-text) – zoran404 Oct 12 '14 at 12:56

3 Answers3

31

If you mean children, element instances have childNodes (which includes non-element children like text nodes) and (on most engines) children (which just has child elements). (You clarified you mean descendants.)

If you mean descendants, you can use querySelectorAll:

var descendants = theElement.querySelectorAll("*");

All modern browsers, and IE8, have querySelectorAll.

It gives you a NodeList, which is array-like. If you want a true JavaScript array, you can use Array.prototype.slice to get it, like this:

var descendants = Array.prototype.slice.call(theElement.querySelectorAll("*"));

Or you can use Array.from (added in ES2015, but easily polyfilled):

var descendants = Array.from(theElement.querySelectorAll("*"));

Now that most environments made NodeList iterable (and you can polyfill it trivially if they don't), you can also use spread notation in an ES2015+ environment:

var descendants = [...theElement.querySelectorAll("*")];

Example:

var descendants = Array.prototype.slice.call(
  document.querySelector(".parent").querySelectorAll("*")
);
descendants.forEach(function(descendant) {
  display(descendant.className);
});
function display(msg) {
  var p = document.createElement('p');
  p.innerHTML = String(msg);
  document.body.appendChild(p);
}
<div class="parent">
    <div class="child1">
        <span class="child2">
            <div class="child3">
                <div class="child4">
                    <span class="child5"></span>
                </div>
                <div class="child6">
                    <div class="class7"></div>
                </div>
            </div>
        </span>

        <div class="child8"></div>
        <span class="child9">
            <div class="child10"></div>
        </span>
    </div>
</div>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Ah sorry and thanks for letting me know! I couldn't find what the hashtag meant. Does it have a name? – Gust van de Wal Jul 02 '19 at 13:44
  • 1
    @GustvandeWal - I don't think so. :-) And to be fair, it seems to be falling out of favour... That's probably because of the upcoming private properties, though the syntax is slightly different. Meh, I should use `Array.prototype.slice`. :-) – T.J. Crowder Jul 02 '19 at 13:50
10

Use theElement.getElementsByTagName("*") rather than theElement.querySelectorAll("*") - because it is faster. getElementsByTagName is also better supported in older browsers.

This returns an HTMLCollection, which is Array-like. You specified that you want it as an Array. To convert it to a real Array, do like this:

Array.prototype.slice.call(theElement.getElementsByTagName("*"))

Should you want even better browser support, you can use jQuery 1.12.4 or picoQuery, which is an reimplementation of jQuery, where you can select which methods you need in an online builder. In this case, you need no methods, as selection is part of core, and the build is only 1kb gzipped. picoQuery is written for modern browsers, but falls back to jQuery 1.12.4 for older browsers

rosell.dk
  • 2,228
  • 25
  • 15
0
document.querySelector('.parent').querySelectorAll('*')

First we find the element (you can do this however you want), then select all descendants using querySelectorAll().

Scimonster
  • 32,893
  • 9
  • 77
  • 89