Iterate Through Elements With The Same Class And Remove Them
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
- Click the yellow button to disable the targeted
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"