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?

Nicholas Daley-Okoye
  • 2,267
  • 1
  • 18
  • 12
nikhil rao
  • 381
  • 3
  • 6
  • 9
  • 1
    cuz when you removing elements from dom, you changing initial `x` array – Kirill Pisarev Feb 04 '15 at 08:02
  • how to remove all the buttons? – nikhil rao Feb 04 '15 at 08:03
  • 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. – jfriend00 Feb 04 '15 at 08:04

6 Answers6

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();
    }
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • document.getElementsByClassName("buddy_blocks").remove() would do in JS? does not work. some syntax mistake? – nikhil rao Feb 04 '15 at 08:06
  • @nikhilrao - no that would not work because a nodeList or HTMLCollection do not have a `.remove()` method that operates on the whole collection. – jfriend00 Feb 04 '15 at 08:07
  • @nikhilrao - I added a plain JS way. – jfriend00 Feb 04 '15 at 08:10
  • @nikhilrao - I fixed an error in my answer. `.remove()` is not a DOM method either. You have to use `.removeChild()` for plain Javascript. – jfriend00 Feb 04 '15 at 08:20
  • Or you can do `var x = Array.from(document.getElementsByClassName("buddy_blocks"));` – fourk Nov 03 '21 at 19:59
  • @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. – jfriend00 Nov 03 '21 at 20:45
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();
}
kindasimple
  • 2,427
  • 1
  • 16
  • 20
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();
}
Nicholas Daley-Okoye
  • 2,267
  • 1
  • 18
  • 12
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]);              
}
user3425506
  • 1,285
  • 1
  • 16
  • 26
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

Kirill Pisarev
  • 844
  • 4
  • 11
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++;
    }
}
shawnnyglum
  • 211
  • 4
  • 14