Lone Learner
Lone Learner

Reputation: 20698

How to remove multiple child nodes recursively without messing up the indices?

JSFiddle URL: http://jsfiddle.net/sFe45/

Code:

<html>
    <head>
        <title>Foo</title>
        <script type="text/javascript">

var target;
var anchor;

function removeTags(node){
    for (var i = 0; i < node.childNodes.length; i++) {
        var childNode = node.childNodes[i];
        if (childNode.nodeType == 1) {
            node.removeChild(childNode);
            continue;
        } 
        removeTags(childNode);
    }
}

window.onload = function() {
    target = document.getElementById('target');
    anchor = document.getElementById('anchor');
    anchor.onclick = function() {
        removeTags(target);
    }
}

        </script>
    </head>
    <body>
        <div id="target">
            <p>
                <a href="#" id="anchor">Remove tags</a>
            </p>

            Text

            <p>Para 1</p>
            <p>Para 2</p>
            <p>Para 3</p>
            <p>Para 4</p>
            <p>Para 5</p>
            <p>Para 6</p>
            <p>Para 7</p>
            <p>Para 8</p>
            <p>Para 9</p>
            <p>Para 10</p>
            Text
        </div>
</html>

​As you will notice in the JSFiddle URL, when you click the "Remove tags" link, removeTags() fails to remove alternate paragraph elements. The reason is when a removeTags removes a child node from its parent, the remaining child nodes shift one place to left in node.childNodes array.

How can this be fixed in a neat way?

Upvotes: 0

Views: 2151

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075189

Count backward:

for (var i = node.childNodes.length - 1; i >= 0; i--) {

Updated fiddle

Alternately, you can use lastChild and previousSibling:

var prev;
for (var child = node.lastChild; child; child = prev) {
    prev = child.previousSibling;

    if (child.nodeType == 1) {
        node.removeChild(child);
        continue;
    } 

    removeTags(child);
}

Updated fiddle

Separately:

...the remaining child nodes shift one place to left in node.childNodes array...

NodeLists are not arrays.

Upvotes: 3

Related Questions