Skip to content Skip to sidebar Skip to footer

Iterate Through Elements With The Same Class And Remove Them

I'm building an app and I need to remove all link elements with a specific class from the header. I've built an example of the problem I'm having in the w3schools editor. For the p

Solution 1:

The problem is that getElementsByClassName returns a liveHTMLCollection - if you remove an element from it during an iteration, the collection will change when you remove it. For example:

const foos = document.getElementsByClassName('foo');
console.log(foos[1].textContent);
foos[0].remove();
console.log(foos[1].textContent);
<divclass="foo">a</div><divclass="foo">b</div><divclass="foo">c</div>

It's quite unintuitive. Either iterate backwards through the collection (eg, from length - 1, to length - 2, ... 0), to ensure every element gets iterated over, or use querySelectorAll instead, which returns a staticNodeList:

const links = head.querySelectorAll('.link-to-remove');

Another benefit to querySelectorAll is that newer browsers support forEach on NodeLists, so you can iterate over them directly, rather than having to use an ugly for loop:

document.querySelectorAll('head .link-to-remove').forEach((removeMe) => {
  removeMe.remove();
});

(as you can see, there's no need to select the head if you put the head in the query string passed to querySelectorAll - you may also remove() an element directly, rather than having to reference its parent and use removeChild)

Solution 2:

The getElementsByTagName method returns a live HTML element collection when you removed an element from DOM it will get updated so it will skip some elements since the index of the element is changing.

To make it works to use a variable which holds the length of collection and iterate backward.

functionremoveLinks() {
  const head = document.getElementsByTagName('head')[0];
        const links = head.getElementsByClassName('link-to-remove');
        let i = links.length;
        while(i--) {
            head.removeChild(links[i]);
        }
}

Or alternately, you can use forEach as well

functionremoveLinks() {
  const head = document.getElementsByTagName('head')[0];
  const links = head.getElementsByClassName('link-to-remove');
  links.forEach(el => el.remove())     
}

Much simpler one using querySelectorAll, forEach and remove methods.

functionremoveLinks() {
  document.querySelectorAll('head .link-to-remove').forEach(el => el.remove())     
}

Solution 3:

you have to set the stylesheet to be disabled as it keeps the css styles in memory so removing the element will not work, it can also cause it to crash in some instances if I remember correctly.

functionremoveLinks() {
  const head = document.getElementsByTagName('head')[0];
        const links = head.getElementsByClassName('link-to-remove');
        for(let i = 0; i < links.length; i++) {
            links[i].disabled = true;
        }
}

Eg:document.styleSheets[0].disabled = true;

Jquery way => $('link[title=mystyle]')[0].disabled=true;

Solution 4:

<link>s can be removed like any other tag. The older methods like .getElementsByClassName(), .getElementsByTagName(), and .getElementsByName() are Live HTMLCollections (an array-like object) so the .length is updated every iteration and it diminishes and prematurely ends the loops. You can achieve your objective by disabling each <link> instead of removing them (.length isn't touched.) or use a collection method that returns a static NodeList (an array-like object) like the more versatile .querySelectorAll() method. Another way is to convert an array-like object into an array by Array.from() This demo:

  • shows two different interfaces to handle <link>

    • First one uses the styleSheet Object of the CSSStyleSheet interface

      • Click the yellow button to disable the targeted <link>s
    • Second HTMLLinkElement interface of the DOM using .querySelectorAll()

      • Click the red button to to remove the targeted <link>s

      • Note: A Live HTMLCollection was made so an accurate count could be made of the link.link-to-remove in the console when the they are removed.

To properly test each example, rerun the demo and then click the other button.

<!DOCTYPE html><html><head><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"class="link-to-remove"><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"class="link-to-remove"><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"class="link-to-remove"><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"class="link-to-remove"></head><body><buttonclass='btn btn-warning'>CLICK TO DISABLE ALL STYLESHEETS</button><ahref='#/'class='btn btn-danger'>REMOVE ALL <code>link.link-to-remove</code></a><script>// Collect all stylesheets and convert to an arraylet sheets = Array.from(document.styleSheets);

    console.log('=========STYLESHEET QTY===========');

    // Test: Check how many stylesheets there areconsole.log('This page has ' + sheets.length + ' stylesheets');

    console.log('=============All HREF=============');

    // Test: View each stylesheet hreffor (let sheet of sheets) {
      console.log(sheet.href);
    }

    document.querySelector('button').onclick = function(e) {
      // Start disabling all stylesheets beginning at the 3rd position for (let s = 0; s < sheets.length; s++) {
        if (s >= 2) {
          sheets[s].disabled = true;
        }
      }

      console.log('=============DISABLED=============');

      // Test: See which stylesheets were disabledfor (let sheet of sheets) {
        console.log(sheet.disabled);
      }
    }

    let nodeList = document.querySelectorAll('.link-to-remove');
    let htmlCol = document.getElementsByClassName('link-to-remove');

    document.querySelector('a').onclick = function(e) {
      nodeList.forEach(link => link.remove());

      console.log('=========STYLESHEET QTY===========');

      // Test: Check how many stylesheets there areconsole.log('This page has ' + htmlCol.length + ' stylesheets with the className: .link-to-remove');

      console.log('=============All CLASS=============');

      // Test: View each all link.classfor (let tag of htmlCol) {
        console.log(tag.className);
      }
    }
  </script></body></html>

Post a Comment for "Iterate Through Elements With The Same Class And Remove Them"