I would like to know how to select all elements with class names "widget" and "hover" and then remove class "hover" from these elements.

I have the following JavaScript code that selects all elements with class "widget" and "hover":

var elements = document.getElementsByClassName('widget hover');
console.log(elements);

This seems to work and outputs something like this (with no errors):

[div#.widget... 

The problem is that if I try to remove the class "hover", I get an error:

var elements = document.getElementsByClassName('widget hover');
console.log(elements);
elements.classList.remove("hover");

This outputs:

[item: function]
length: 0
Uncaught TypeError: Cannot call method 'remove' of undefined 

Can anyone tell me what I'm doing wrong?


Please note that I have it working in jQuery:

$('.widget.hover').removeClass('hover');

... but I'm looking for a solution in pure JavaScript.

有帮助吗?

解决方案

var elems = document.querySelectorAll(".widget.hover");

[].forEach.call(elems, function(el) {
    el.classList.remove("hover");
});

You can patch .classList into IE9. Otherwise, you'll need to modify the .className.

var elems = document.querySelectorAll(".widget.hover");

[].forEach.call(elems, function(el) {
    el.className = el.className.replace(/\bhover\b/, "");
});

The .forEach() also needs a patch for IE8, but that's pretty common anyway.

其他提示

It's 2023... keep it simple and just use es6

Times have changed and now the cleanest and most readable way to do this is:

Array.from(document.querySelectorAll('.widget.hover')).forEach(
  (el) => el.classList.remove('hover')
);

If you can't support arrow functions then just convert it like this:

Array.from(document.querySelectorAll('.widget.hover')).forEach(function(el) { 
    el.classList.remove('hover');
});

Additionally if you need to support extremely old browsers then use a polyfil for the forEach and Array.from and move on with your life.

Find elements:

var elements = document.getElementsByClassName('widget hover');

Since elements is a live array and reflects all dom changes you can remove all hover classes with a simple while loop:

while(elements.length > 0){
    elements[0].classList.remove('hover');
}

Elements is an array of DOM objects. You should do something like this:

for (var i = 0; i < elements.length; i++) {
   elements[i].classList.remove('hover');
}

Enumerate the elements collection and for each element inside the collection call the remove method

For ES6, this can be done in a few ways with one liners, where you create an array of the elements with the spread operator ..., and remove the class with the map operator:

With querySelectorAll:

[...document.querySelectorAll('.widget')].map(x => x.classList.remove('hover'));

With getElementsByClassName:

[...document.getElementsByClassName('widget')].map(x => x.classList.remove('hover'));

For querySelectorAll, notice the use of .widget instead of widget. An alternative for the spread operator would be to use Array.from like:

Array.from(document.querySelectorAll('.widget')).map(x => x.classList.remove('hover'));

This might help:

let allElements = Array.from(document.querySelectorAll('.widget.hover'));
for (let element of allElements) {
  element.classList.remove('hover');
}

I use a simple method. If you always process [0] in the required number of loops, you can apply the process to all.

The HTMLCollection(elements) changes in real time, so put the length in a variable. (l = element.length)

for(var elements = document.getElementsByClassName('widget hover'), i = 0, l = elements.length; l > i; i++) {
  elements[0].classList.remove("hover");
}
var elems = document.querySelectorAll(".widget.hover");

 for(let elem of elems){
        elem.classList.remove('hover');
        }

Given worked for me.

document.querySelectorAll(".widget.hover").forEach(obj=>obj.classList.remove("hover"));
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top