Javascript remove not removing all elements
Asked Answered
S

6

5

Please refer fiddle - http://jsfiddle.net/fkwwyvz8/

x = document.getElementsByClassName("buddy_blocks");
for(i=0;i<x.length;i++)
    x[i].remove();

Click on the last button, and it had to remove all the other buttons, but it does not and only removes some of them, not sure why? And any way to remove all those buttons?

Swaney answered 4/2, 2015 at 8:1 Comment(3)
cuz when you removing elements from dom, you changing initial x arrayEre
how to remove all the buttons?Swaney
Please post all relevant code in your question. Questions where necessary parts of the code are ONLY in external references are considered off-topic here on StackOverflow. This is because external references tend to disappear or change over time, rendering the question useless in time and not a useful reference.Incapacious
I
7

Since you appear to have jQuery in your code already, you can just use this to remove all buttons:

$(".buddy_blocks").remove();

Your attempt was not working for two reasons:

  1. document.getElementsByClassName() returns a dynamic nodeList that changes underneath you each time you remove an element which causes you to miss elements in your iteration
  2. Because a DOM element does not have a .remove() method (in most browsers anyway - it is a proposed method, but isn't widely available yet). The parent has a .removeChild() method you can use instead.

In plain Javascript, you could set up your iteration backwards so that when you remove elements and when this causes the dynamic HTMLCollection to change, it will not mess up your iteration because the changes will be the elements that you have already passed by. And, switch to use .removeChild() like this:

function f() {
    var x = document.getElementsByClassName("buddy_blocks");
    for(var i = x.length - 1; i >= 0; i--) {
        x[i].parentNode.removeChild(x[i]);
    }
}

Also, please use var on all variables that are intended to be local to your function so you are not creating "accidental global variables" which will cause hard to figure out bugs at some time in the future.


Or, in modern browsers as of 2021, you can use document.querySelectorAll() (because it doesn't return a live collection and is iterable) and you can use .remove() since all modern browsers support it:

function f() {
    const items = document.querySelectorAll(".buddy_blocks");
    for (let item of items) {
         item.remove();
    }
}
Incapacious answered 4/2, 2015 at 8:5 Comment(6)
document.getElementsByClassName("buddy_blocks").remove() would do in JS? does not work. some syntax mistake?Swaney
@nikhilrao - no that would not work because a nodeList or HTMLCollection do not have a .remove() method that operates on the whole collection.Incapacious
@nikhilrao - I added a plain JS way.Incapacious
@nikhilrao - I fixed an error in my answer. .remove() is not a DOM method either. You have to use .removeChild() for plain Javascript.Incapacious
Or you can do var x = Array.from(document.getElementsByClassName("buddy_blocks"));Sterlingsterlitamak
@FourCinnamon0 - Or, you can do document.querySelectorAll(".buddy_blocks") since this doesn't return a live collection and is directly iterable. As this is an older answer, I updated it to show this option in modern browsers.Incapacious
P
2

When iterating over an array and modifying it, start at the last index to avoid side effects to the current index position when you remove items

$("#c").click(function() {
  f();
});

function f() {
  x = document.getElementsByClassName("buddy_blocks");
  for(i=x.length-1;i>=0;i--)
    x[i].remove();
}
Paronychia answered 4/2, 2015 at 8:10 Comment(0)
C
2

You were looping forward through the elements.

x = document.getElementsByClassName("buddy_blocks");
for(i=0;i<x.length;i++)
    x[i].remove();

x is a NodeList not an array. It is a live view onto the current elements that matches the elements with that class. So when you delete the first item, what was the first item is no longer in the list, and the second item is now the first item. But, you've moved on to what was the third item, but is the new second item.

The end result is you're only removing half of the elements.

Consider either this:

//remove the first item from the NodeList until there is nothing left
x = document.getElementsByClassName("buddy_blocks");
while(x.length > 0) {
    x[0].remove();
}

or:

//remove from the end of the list, which won't cause other elements to change position
x = document.getElementsByClassName("buddy_blocks");
for(i=x.length-1;i>=0;i--) {
    x[i].remove();
}
Chema answered 4/2, 2015 at 8:14 Comment(0)
K
2

I ran into the same problem and have spent a couple of hours struggling with it. With the help of other answers on this page, I have come up with :

x = document.getElementsByClassName("buddy_blocks");                  
while(x.length){                                                      
  x[0].parentElement.removeChild(x[0]);              
}
Kynthia answered 2/11, 2021 at 18:6 Comment(0)
E
1

jQuery way to remove all elements with class 'buddy_blocks':

$(".buddy_blocks").remove();

fiddle

plain javascript way:

var elems = document.getElementsByClassName('buddy_blocks'),
    elem;
while(elems.length){
    elem = elems.item(0);
    elem.parentNode.removeChild(elem);
}

fiddle

Ere answered 4/2, 2015 at 8:5 Comment(1)
using JS is there a way?Swaney
R
0

Reason for such a behavior is the variable containing the DOM element "x" is pointing to the live DOM element. So every time you remove one element, the "x" is holding the new DOM structure. So we need to use the while loop below and keep removing the 1st child from the DOM.

$("#c").click(function() {
  f();
});
function f() {
   x = document.getElementsByClassName("buddy_blocks");
//for(i=0;i<x.length;i++)
//x[i].remove();
    var i = 0;
    while(x.length) {
     x[0].remove();
        i++;
    }
}
Rockwell answered 4/2, 2015 at 8:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.