Camden Narzt
Camden Narzt

Reputation: 2003

JS removeChild only works half the time

var graph = document.getElementById('graph');
Array.prototype.forEach.call(document.getElementsByClassName('release'),graph.removeChild.bind(graph));

In Firefox and Safari (haven't tested others) this removes only the even indexed elements, why?

The HTMLCollection is indexed from 0 to the correct length incrementing by 1, and all elements are present. I get the same behavior with a normal for loop too, so it's probably not some weird forEach incompatibility. In fact if I use the function function(e,i,a){console.log(e.innerHTML);graph.removeChild(e)} instead, all the innerHTML gets logged, but still only the even indexed nodes get removed.

Upvotes: 1

Views: 49

Answers (1)

dfsq
dfsq

Reputation: 193261

This is because you are using getElementsByClassName which returns live HTMLCollection. So what happens is that index of this collection shifts once the item is removed (collection is updated automatically), which results in undeleted left-over items.

var graph = document.getElementById('graph');
Array.prototype.forEach.call(document.getElementsByClassName('release'), graph.removeChild.bind(graph));
<div id="graph">
    <div class="release">release 1</div>
    <div class="release">release 2</div>
    <div class="release">release 3</div>
</div>

Use non-live NodeList, for example returned by querySelectorAll:

var graph = document.getElementById('graph');
Array.prototype.forEach.call(document.querySelectorAll('.release'), graph.removeChild.bind(graph));

var graph = document.getElementById('graph');
Array.prototype.forEach.call(document.querySelectorAll('.release'), graph.removeChild.bind(graph));
<div id="graph">
    <div class="release">release 1</div>
    <div class="release">release 2</div>
    <div class="release">release 3</div>
</div>

Upvotes: 2

Related Questions