2

I'm trying to print DOM content recursively.

(function print (node) {
    for (var i = 0, elem; i < (elem = node.childNodes[i]); i++) {
        print(elem);
    }
})(document.documentElement);

When I fire my code in browser console I get

undefined

What I'm doing wrong?

barbara
  • 3,111
  • 6
  • 30
  • 58
  • 2
    I know that Javascript's type coercion is supercool and that, but can a number really be less (or more) than an HtmlElement? – spender Sep 29 '14 at 12:13
  • How are you defining `node` in your function. Also your for loop comparison of `i` needs to be comparing to an integer (maybe `node.childNodes.length`). The `elem = node.childNodes[i]` is something you'd need in the loop itself. – RichieAHB Sep 29 '14 at 12:14
  • And what if an element doesn't have childnodes? – Andy Sep 29 '14 at 12:14
  • Well once you get the loop to work, you never write to the console... – epascarello Sep 29 '14 at 12:20
  • Is the problem actually how to print the DOM recursively, or how to print the DOM and you think the best way might be recursively? There are non-recursive solutions which could be equally good or some might say better. –  Sep 29 '14 at 12:44

4 Answers4

2

Try this: (it works in chrome, i am not sure if every browser has the same structure for document)

(function print (node) {
    console.log(node)
    var childNodes = node.childNodes;
    for (var i = 0; i < childNodes.length; i++) {
        print(childNodes[i]);
    }
})(document);

Edit: Warning, the console is rather slow to print to, be warned :P
Update: Removed "elem" as it was not used and i had only forgotten to remove it

Snellface
  • 598
  • 5
  • 12
  • And is there any restriction in `JavaScript` for recursive calls? Or it depends only on particular `JavaScript Engine` implementation? – barbara Sep 29 '14 at 12:27
  • The stack size is probably the only limit you will have to worry about. At least in "regular" programming languages like c, c++, java, c#, to mention a few, each function call will add data to the stack. The stack have a maximum size (usually set by the OS or any VM you are running in, in this case the javascript engine in your browser). If this stack gets full you will get what is called a "Stack overflow" (this sites name ;)) and your program will terminate. You usually don't need to worry about the stack size though. I will add as another comment an example where this is a problem – Snellface Sep 29 '14 at 12:31
  • What is the variable `elem` used for? –  Sep 29 '14 at 12:31
  • @torazaburo Yes, it's redundant. You can remove it. – barbara Sep 29 '14 at 12:34
  • If you type a function like this: (function CrashStuff(){CrashStuff();})() you will, in chrome, get the error: "RangeError: Maximum call stack size exceeded". Normally when you call a function, it is added to the stack, and once you are done executing your function it is removed from the stack. – Snellface Sep 29 '14 at 12:37
  • Yes, every browser has the same DOM structure and APIs. –  Sep 29 '14 at 12:38
  • If you have function A calling function B, your stack would look like [A], then you make your call to B and you have [A][B], and when B is done you have [A] again, and when A is done your stack is empty. If you have a function A that always calls itself, you will have a stack that looks like: [] then [A] then [A][A], then [A][A][A] and so forth till it can no longer hold more [A]'s :P.. – Snellface Sep 29 '14 at 12:38
  • Yes, I know what does `recursion` mean :) What is really interesting it's the numbers. How many calls you can make to crush for example Chrome or Safari. – barbara Sep 29 '14 at 12:39
  • @torazaburo yes, elem was there by mistake, i had copied the example in the question and forgot to remove it :P – Snellface Sep 29 '14 at 12:40
  • @barbara Ah, well, the size really depends on what environment you run your application in. There is a thread about this here: http://stackoverflow.com/questions/7826992/browser-javascript-stack-size-limit (google is your friend <3) – Snellface Sep 29 '14 at 12:42
2
function traverseDOM(node){
    var result = node.tagName;
    if (node.hasChildNodes()) {
      var child = node.firstChild;
      while (child) {
        if (child.nodeType === 1) {
          result += traverseDOM(child)
        }
        child = child.nextSibling;
      }
    }
    return result;
  }
 console.log(traverseDOM());
dReAmEr
  • 6,986
  • 7
  • 36
  • 63
  • Actually, the `if (node.hasChildNodes())` test is redundant, since if there are no child nodes, `node.firstChild` will be null, and the loop `while (child)` will never execute. –  Sep 29 '14 at 12:36
0

Depends on whether it's a laser printer or a dot-matrix printer.

I suggest using the TreeWalker API, which does this for a living.

var node;
var walker = document.TreeWalker(document, 
    NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);

while (node = walker.nextNode) { console.log(node); }

This will also avoid any recursion/stack overflow issues, although in reality that's probably not an issue even in the case of very deep DOMs.

0
function print(document){
    var data=document.documentElement;
    for(var i=0;i<data.childNodes.length;i++)
    {
        print(data.childNodes[i]);
    }
}
console.log(documentdocumentElement)
Gottlieb Notschnabel
  • 9,408
  • 18
  • 74
  • 116
SULFIKAR A N
  • 436
  • 4
  • 13