2

I wrote the following page as a DOM traversal demo:

<html>
    <head>
        <title>DOM Traversal</title>
    </head>
    <body>
        <h1>Sample H1</h1>
        <div id="text">
            <p>Sample paragraph</p>
        </div>
    </body>
    <script>
        // Traversing the DOM tree
        "use strict";

        var node = document.body;

        while(node) {
            console.log(node);
            node = node.lastChild;
        }
    </script>
</html>

Surprisingly, the output I'm getting is the body tag followed by the script tag. How is this possible? Isn't the script tag a sibling of the body tag? Also, why aren't the child nodes of body being traversed?

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
ankush981
  • 5,159
  • 8
  • 51
  • 96
  • 3
    Scripts should be inside the body. Perhaps your browser is correcting your non-standard markup for you. http://stackoverflow.com/questions/3037725/is-it-wrong-to-place-the-script-tag-after-the-body-tag – isherwood Jun 03 '14 at 13:15
  • 1
    @isherwood: or in the ``... – Cerbrus Jun 03 '14 at 13:16
  • Right. I meant as opposed to after it. – isherwood Jun 03 '14 at 13:16
  • Just tested your code in several browsers. it seems that most of them show script as a sibling of body and as a child of it (it shows up twice, with the same content). And on all of them it does traverse the children as well (please read Uweb's answer to see why it might not for you) – Catalin Deaconescu Jun 03 '14 at 13:26

3 Answers3

5

You cannot add your script element outside of the head or body elements. The browser is auto-correcting your HTML, moving the script into the end of your body, which explains the result you are getting.

The html element may only contain the head and body elements as its children. Anything else must be placed within these two elements.

iMoses
  • 4,338
  • 1
  • 24
  • 39
  • Thanks for the answer. Please see my updated code here http://pastebin.com/4n97tv4v. I should now get body -> div -> p but am getting body -> #text (would be great if you could run this at your end). What's wrong now? – ankush981 Jun 03 '14 at 13:49
  • Text is also a node which means that the blank space between your elements is actually a text node. That's what you receive. – iMoses Jun 03 '14 at 14:47
4

On top of what iMoses said, your script block will run before the entire document is parsed, as it doesn't wait on the domReady event. This seems to cause a race condition.

If you leave your script where it is, but wait for domReady, you get a slightly different result (albeit still not what you want).

EDIT: change your script to output "node.outerHTML" instead, and you will see that the script block gets moved or rather duplicated into the body. Without waiting for document ready, you end up with two script blocks while the script is running - one is your original, the other one at the end of the body as iMoses pointed out. Waiting for document ready, you will find that only the (moved) one inside the body remains.

UweB
  • 4,080
  • 2
  • 16
  • 28
2

A good place to start with resolving this kind of 'issue' is to validate the source first.

Tools such as the W3C HTML validator will help you avoid this kind of problem going forward:

http://validator.w3.org/check

Validating your code returns the following:

Line 11, Column 12: document type does not allow element "SCRIPT" here
<script>


The element named above was found in a context where it is not allowed. This could mean that you have incorrectly nested elements -- such as a "style" element in the "body" section instead of inside "head" -- or two elements that overlap (which is not allowed).

One common cause for this error is the use of XHTML syntax in HTML documents. Due to HTML's rules of implicitly closed elements, this error can create cascading effects. For instance, using XHTML's "self-closing" tags for "meta" and "link" in the "head" section of a HTML document may cause the parser to infer the end of the "head" section and the beginning of the "body" section (where "link" and "meta" are not allowed; hence the reported error).
dougajmcdonald
  • 19,231
  • 12
  • 56
  • 89