I just want to change a classname to another one.
I've tried using
document.getElementsByClassName("current").setAttribute("class", "none");
but it doesn't work. I'm new at javascript.
To replace a DOM element in the DOM tree, you follow these steps: First, select the DOM element that you want to replace. Then, create a new element. Finally, select the parent element of the target element and replace the target element by the new element using the replaceChild() method.
document.getElementsByClassName
returns an HTMLCollection
, not just an array of elements. That means that the collection is live, so in this specific situation, it retains the requirement that it will always hold all elements with the class "current".
Coincidentally, you are removing the very class
that the collection depends on, therefore updating the collection. It would be totally different if you were setting the value
property (for example) in the loop - the collection wouldn't be affected, because the class
"current" wasn't removed. It would also be totally different if you were adding a class, such as el.className += " none";
, but that isn't the case.
A great description from the MDN docs:
HTMLCollections in the HTML DOM are live; they are automatically updated when the underlying document is changed.
An easy way to overcome all this pandemonium is by looping backwards.
var els = document.getElementsByClassName('current'),
i = els.length;
while (i--) {
els[i].className = 'none';
}
DEMO: http://jsfiddle.net/fAJgT/
(the code in the demo has a setTimeout
, simply so you can see the original border color at first, then after 1.5 seconds, see it change)
This works because it modifies the last item in the collection - when it is modified (and automatically removed), move onto the item before it. So it doesn't suffer any consequences of the automatic removal.
An alternate setup, doing the same thing, is:
for (i = els.length; i >= 0; i--) {
Another answer made me realize you could just continually operate on the first item found. When you remove the specific class, the element is removed from the collection, so you're guaranteed that the first item is always a fresh item in the collection. Therefore, checking the length
property should be a safe condition to check. Here's an example:
var els = document.getElementsByClassName('current');
while (els.length) {
els[0].className = 'none';
}
DEMO: http://jsfiddle.net/EJLXe/
This is basically saying "while there's still items in the collection, modify the first one (which will be removed after modified)". I really wouldn't recommend ever using that method though, because it only works specifically because you end up modifying the collection. This would infinitely loop if you were not removing the specific class, or with a normal array or a non-live collection (without splice
ing).
Another option is to slice
(shallow copy) the collection into an array and loop through that normally. But I don't see any reason/improvement to do that. Here's an example anyways:
var els = document.getElementsByClassName('current'),
sliced = Array.prototype.slice.call(els), i;
for (i = 0; i < sliced.length; i++) {
sliced[i].className = 'none';
}
DEMO: http://jsfiddle.net/LHe95/2/
Finally, you could use document.querySelector
- it returns a non-live NodeList
(therefore you can loop like normal), and even has better support in browsers than document.getElementsByClassName
does. Here's an example:
var els = document.querySelectorAll('.current'),
i;
for (i = 0; i < els.length; i++) {
els[i].className = 'none';
}
DEMO: http://jsfiddle.net/xq8Xr/
References:
document.getElementsByClassName
: https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByClassName
HTMLCollection
: https://developer.mozilla.org/en-US/docs/DOM/HTMLCollection
slice
: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice
querySelectorAll
: https://developer.mozilla.org/en-US/docs/DOM/Document.querySelectorAll
document.getElementsByClassName("current")
returns a HTMLCollection
, not an HTMLElement
. You can access elements in the list the same way you would access an array.
The following will change the class of the first element in the HTMLCollection
.
document.getElementsByClassName("current")[0].setAttribute("class", "none");
However, you do not have to use the setAttribute
method, you can just set the className
property of the element.
element.className = 'none';
Please note that HTMLCollection
are live, wich means that as soon as the element will not have the current
class name anymore, the element will be removed from the array, so to avoid any issues you could iterate over it using the following approach:
var list = document.getElementsByClassName("current");
while (list.length) {
list[0].className = 'none';
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With