Removing HTML Element children with JavaScript

Just a quick fyi, but if you are doing work in JavaScript and need to dynamically remove all of the childNodes from a DOM element, make sure to do it with a while loop, and not a for loop.

For example, this is bad:


[code]function removeChildrenFromNode(node){if(node !== undefined &&node !=== null){return;}var len = node.childNodes.length;for(var i = 0; i < len; i++){node.removeChild(node.childNodes[i]);}}[/code]Since, as soon as you remove one child, the length of node.childNodes is 1 smaller, and you will eventually access an index that does not exist (and get a JavaScript error / exception).The correct way to do this is with a while loop with node.hasChildNodes, like so:[code]function removeChildrenFromNode(node){if(node !== undefined &&node !=== null){return;}var len = node.childNodes.length;while (node.hasChildNodes()){node.removeChild(node.firstChild);}}[/code]I just spent quite a bit of time debugging this. In fact, I am pretty sure that this is why the Macromedia News Firefox extension does not currently work well in Firefox 1.5. The odd thing is that this was not an issue prior to Firefox 1.5 (at least not in the Firefox extension).Anyways, just a little heads up of something to watch out for.Thanks to everyone on the Firefox development forums for helping me track this down.

19 Responses to Removing HTML Element children with JavaScript

  1. flashape says:

    yeah, i ran into a similar issue: http://www.visible-form.com/blog/000178.html . Of cours, as someone pointed out in the comments to that post, since you are dealing with a tree structure, a better way would probably be to keep track of the highest removable element in the tree and remove that.

  2. Tangent says:

    Using reversed FOR loop is another solution to this problem, where you would write it as for (var i = len – 1; i >= 0; i++)

  3. Mike,Since the node.hasChildNodes() will always do an evaluation, you can also always do a decremental for() loop.for( var i=len; i > -1; i– ){node.removeChild(node.childNodes[i]);}This should be a little more efficient since you’re not always doing an evaluation. However, if you have any asynchronous events going on that could be adding to the DOM, the node.hasChildNodes() method would be sure to get all the elements.

  4. Michel says:

    I wonder whether the most effective solution would not be :for(var i = 0; i

  5. mike chambers says:

    >Since the node.hasChildNodes() will always do an evaluation, you can also always do a decremental for() loop.one minor correction. It should be len – 1 like so:[code]for( var i=len – 1; i > -1; i– ){node.removeChild(node.childNodes[i]);}[/code](this is how i fixed the firefox extension).mike chambersmesh@adobe.com

  6. mike chambers says:

    >I wonder whether the most effective solution would not be :Well, the issue is the use of len, since as soon as you remove something, len is not longer valid.mike chambersmesh@adobe.com

  7. Mark Wubben says:

    What about:while(node.firstChild) node.removeChild(node.firstChild);This removes the need to call `hasChildNodes()` every time nor do you have to keep referencing the `childNodes` collection (which is a live collection, so takes up some resources).

  8. mwarden says:

    Thanks for the code. I ended up with this function:function removeChildrenRecursively(node){if (!node) return;while (node.hasChildNodes()) {removeChildrenRecursively(node.firstChild);node.removeChild(node.firstChild);}}

  9. There is a simpler way to remove all children from a node (named parent here):while ( parent.hasChildNodes() ) { parent.removeChild(parent.firstChild); }and you really don’t need to recursively remove the children : removing the parent is sufficient.

  10. Chris L says:

    Thanks for the great tips, this was bugging me for the last hour or so. Deleting the parent is usually easier, but not always the best solution.

  11. jvvw says:

    Thanks – this saved me some agony!

  12. Gus says:

    Hi Mike, Thanks for the post. I think you have a logic error in the beginning of your function. You want to return if then node is either null or undefined, and not exit if node neither undefined or null. I think you want this:if(node == undefined || node == null) return;…though it looks like Mark Wubben’s answer is the best.

  13. alternate says:

    What if we donode.innerHTML = “”;Would it remove all the child nodes?

  14. jk says:

    This is much easier:function removeChildrenFromNode(node){if(node !== undefined &&node !=== null){return;}var nodes = node.childNodes;for(var i = 0; i

  15. Rui Nunes says:

    What about just doing this to clear node childs:myNode.innerText=”;

  16. Netrunner says:

    Rui Nunes got it!Thank you!

  17. Kari Chase says:

    I was successfully able to delete nodes with the removeChild/ while loop as you suggested.However, in my case I am adding/removing tr elements as you expand/collapse a tree structure. In firefox it is working perfectly, in IE after items are removed there seems to be blank white space added in there place which pushes all rows below down and looks awkward. Any ideas why IE is doing this?thanks

  18. Andrew says:

    If you wanted to check what you are deleting you could use a for-in loop:for(key in parentNode.childNodes){if(parentNode.childNodes[key].nodeName == ‘IMG’){parentNode.removeChild(parentNode.childNodes[key]);}}

  19. Des Traynor says:

    Many thanks for this Mike, worked a treat.Des