I want to retrieve all the nodes present in particular DIV element.see the below test page (firefox)
New Document <
var getComments = function(oNode) {
var oChild,
aComments = [];
oNode = oNode || document;
for (var n=0; n<oNode.childNodes.length; n++) {
oChild = oNode.childNodes[n];
switch (oChild.nodeType) {
case 1: // Element
aComments = aComments.concat(getComments(oChild));
break;
case 8: // Comment
aComments.push(oChild);
break;
}
}
return aComments;
}
Node types (non exhaustive):
getElementsByTagName
only picks up Element nodes. childNodes
, nextSibling
, etc. pick up all kinds of nodes. nextElementSibling
only picks up Elements.
Comments are nodes in the DOM tree, but they don't have a tag name. The getElementsByTagName
method only returns nodes that have a tag name.
If you want all nodes, you have to traverse the DOM tree, using the childNodes
collection of each element.
The heart of the problem is that these methods...
document.getElementById(...)
document.getElementsByTagName(...)
... return elements, as indicated by their names. However, comments and text nodes are not elements. They are nodes, but not elements.
So you need to do some traditional old fashioned DOM scripting, using childNodes
like Vincent Robert suggested. Since - as you indicate in your comment to him - that .childNodes
only goes one 'layer' deep, you need to define a recursive function to find the comment nodes: (I'm naming mine document.getCommentNodes()
)
document.getCommentNodes = function() {
function traverseDom(curr_element) { // this is the recursive function
var comments = new Array();
// base case: node is a comment node
if (curr_element.nodeName == "#comment" || curr_element.nodeType == 8) {
// You need this OR because some browsers won't support either nodType or nodeName... I think...
comments[comments.length] = curr_element;
}
// recursive case: node is not a comment node
else if(curr_element.childNodes.length>0) {
for (var i = 0; i<curr_element.childNodes.length; i++) {
// adventures with recursion!
comments = comments.concat(traverseDom(curr_element.childNodes[i]));
}
}
return comments;
}
return traverseDom(document.getElementsByTagName("html")[0]);
}
You can use .childNodes
to retrieve all children instead of .getElementsByTagName('*')
which will only return child elements.
Here is a function to retrieve all descendants of a DOM node:
function getDescendantNodes(node)
{
var ret = [];
if( node )
{
var childNodes = node.childNodes;
for( var i = 0, l = childNodes.length; i < l; ++i )
{
var childNode = childNodes[i];
ret.push(childNode);
ret = ret.concat(getDescendantNodes(childNode));
}
}
return ret;
}
Usage:
getDescendantNodes(document.getElementById("foo"));
If you don't care about IE, you could avoid the recursive approach and possibly improve performance (untested) by using a TreeWalker using document.createTreeWalker:
function getCommentNodes(containerNode) {
var treeWalker = document.createTreeWalker(containerNode,
NodeFilter.SHOW_COMMENT, null, false);
var comments = [];
while (treeWalker.nextNode()) {
comments.push(treeWalker.currentNode);
}
return comments;
}
console.log(getCommentNodes(document.body));