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.
Related Entries
- Encapsulating Ajax XMLHTTPRequest Calls within JavaScript classes
- Learning Object Oriented JavaScript Programing from ActionScript
- Parsing XML in JavaScript?
Comments
-
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.
-
TangentUsing reversed FOR loop is another solution to this problem, where you would write it as for (var i = len - 1; i >= 0; i++)
-
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.
-
MichelI wonder whether the most effective solution would not be : for(var i = 0; i
-
mike chambers>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 chambers mesh@adobe.com
-
mike chambers>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 chambers mesh@adobe.com
-
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).
-
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); } }
-
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.
-
Chris LThanks 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.
-
Thanks - this saved me some agony!
-
GusHi 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.
-
alternateWhat if we do node.innerHTML = ""; Would it remove all the child nodes?
-
jkThis is much easier: function removeChildrenFromNode(node) { if(node !== undefined && node !=== null) { return; } var nodes = node.childNodes; for(var i = 0; i
-
Rui NunesWhat about just doing this to clear node childs: myNode.innerText='';
-
NetrunnerRui Nunes got it! Thank you!
-
Kari ChaseI 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
-
AndrewIf 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]); } }
-
Many thanks for this Mike, worked a treat. Des