Renfei Song
Renfei Song

Reputation: 2960

Why my getElementsByTagName returns an empty NodeList?

This is my code:

<html>

<h1 id="hg">
    <h2>11</h2>
    <h2>22</h2>
    <h2>33</h2>
</h1>

<script>
    var h = document.getElementById("hg").getElementsByTagName("h2");
    alert(h.length);
</script>

</html>

I have looked up the manual, it seems that getElementById returns an HTMLHeadingElement in this case, and it inherits the method getElementsByTagName from Element. I expect to get a 3 as the value of h.length, but instead I get 0. What's wrong with it?

Upvotes: 2

Views: 3791

Answers (2)

David Thomas
David Thomas

Reputation: 253396

You'll find that a <h1> cannot contain another heading (the only valid content of an h1, and other headings, is phrasing content, which restricts content to, very simplistically, in-line elements and text), therefore when the browser constructs the DOM it moves the h2 elements outside of the h1, which prevents them being found, by the DOM, inside the h1.

In Chrome, your HTML is reorganised to the following (and, I presume, similarly rearranged in other browsers):

<h1 id="hg"></h1>
<h2>11</h2>
<h2>22</h2>
<h2>33</h2>

This rescuing of the DOM to maintain validity is why we should, as developers, always strive to create valid HTML: because the automatic corrections made by browsers are undocumented and unpredictable (prior to HTML 5, which I think documents how error recovery should proceed).

Incidentally, this sounds very similar to the use-case presented for the <hgroup> element (which seems to be in the process of being dropped from the spec). Given, however, that you appear to be presenting a list of contents I'd suggest enclosing the <h2> elements in an <ol> and semantically grouping them that way:

<ol id="contents">
    <li><h2>11</h2></li>
    <li><h2>22</h2></li>
    <li><h2>33</h2></li>
</ol>

Upvotes: 9

Alessandro Minoccheri
Alessandro Minoccheri

Reputation: 35973

you need to change your html to this for example:

<div id="hg">
    <h2>11</h2>
    <h2>22</h2>
    <h2>33</h2>
</div>

DEMO

Upvotes: 1

Related Questions