I'm performing a small text with JavaScript with the getElementsByClassName()
and I am getting some unwanted results. I would like the script to change each CSS class to a new class. The issue is that every other class is only changing...
I would like to use pure js how this issue as it is for practice purposes.
The first thing that came to mind was white spaces, although when removing the this did not make any differnce.
Can anyone point our what I am doing wrong?
<html> <head> <link rel="stylesheet" type="text/css" href="default.css"> </head> <body> <div class="block-default">BLOCK1</div> <div class="block-default">BLOCK2</div> <div class="block-default">BLOCK3</div> <div class="block-default">BLOCK4</div> <div class="block-default">BLOCK5</div> <div class="block-default">BLOCK6</div> <div class="block-default">BLOCK7</div> <div class="block-default">BLOCK8</div> <script> var blockSet = document.getElementsByClassName("block-default"); var blockSetLength = blockSet.length; blockSet[0].className = "block-selected"; blockSet[1].className = "block-selected"; blockSet[2].className = "block-selected"; blockSet[3].className = "block-selected"; blockSet[4].className = "block-selected"; blockSet[5].className = "block-selected"; blockSet[6].className = "block-selected"; blockSet[7].className = "block-selected"; </script> </body> </html>
CSS Classes:
.block-default { width: 100px; height:50px; background-color: green; border: 1px solid red; padding:10px; } .block-selected { width: 100px; height:50px; background-color: blue; border: 1px solid white; padding:10px; }
The getElementsByClassName method of Document interface returns an array-like object of all child elements which have all of the given class name(s). When called on the document object, the complete document is searched, including the root node.
Absolutely, divs can have more than one class and with some Bootstrap components you'll often need to have multiple classes for them to function as you want them to. Applying multiple classes of course is possible outside of bootstrap as well.
But nothing has changed with it, the semantic meaning of both className and class is the same, when JSX is rendered, the className attribute is automatically rendered as a class attribute.
Because you change the .className
of the blockSet
which is an HTMLCollection
. The collection that have elements with same class (block-default
) will change when the elements suffers some updates.
In other words when you change the .className
of an element the collection will exclude that element. This means that the size of the HTMLCollection
will decrease . Also the size will increase if an element with that class has beed added to the DOM.
To solve this you can always change only the first element .className
.
for(var i = 0; i<blockSetLength; i++) { blockSet[0].className = "block-selected"; }
Notes: Intead of changing class element by element, you can iterate through elements with for
and change .className
.
var blockSet = document.getElementsByClassName("block-default"); var blockSetLength = blockSet.length; console.log(blockSet); for(var i = 0; i<blockSetLength; i++) { blockSet[0].className = "block-selected"; }
.block-default { width: 100px; height:50px; background-color: green; border: 1px solid red; padding:10px; } .block-selected { width: 100px; height:50px; background-color: blue; border: 1px solid white; padding:10px; }
<div class="block-default">BLOCK1</div> <div class="block-default">BLOCK2</div> <div class="block-default">BLOCK3</div> <div class="block-default">BLOCK4</div> <div class="block-default">BLOCK5</div> <div class="block-default">BLOCK6</div> <div class="block-default">BLOCK7</div> <div class="block-default">BLOCK8</div>
If you add a new item in DOM (not collection) the size will increase as presented in the example below.
var blockSet = document.getElementsByClassName("block-default"); var blockSetLength = blockSet.length; alert("Current size: " + blockSet.length); document.body.innerHTML += '<div class="block-default">BLOCK9</div>'; alert("After adding an element in DOM size: " + blockSet.length);
.block-default { width: 100px; height:50px; background-color: green; border: 1px solid red; padding:10px; } .block-selected { width: 100px; height:50px; background-color: blue; border: 1px solid white; padding:10px; }
<div class="block-default">BLOCK1</div> <div class="block-default">BLOCK2</div> <div class="block-default">BLOCK3</div> <div class="block-default">BLOCK4</div> <div class="block-default">BLOCK5</div> <div class="block-default">BLOCK6</div> <div class="block-default">BLOCK7</div> <div class="block-default">BLOCK8</div>
Instead of using getElementsByClassName()
,
which returns a live HTMLCollection that will change as the className
s change,
you can use querySelectorAll()
,
which returns a non-live NodeList that will not change.
querySelectorAll()
has better IE support than getElementsByClassName()
(IE8+ vs. IE9+).
It's also much more flexible since it supports CSS selectors (CSS2 for IE8+ and CSS3 for IE9+).
However, querySelectorAll()
is slower than getElementsByClassName()
.
Keep that in mind if you're processing thousands of DOM elements.
Snippet
var blockSet = document.querySelectorAll(".block-default"); var blockSetLength = blockSet.length; blockSet[0].className = "block-selected"; blockSet[1].className = "block-selected"; blockSet[2].className = "block-selected"; blockSet[3].className = "block-selected"; blockSet[4].className = "block-selected"; blockSet[5].className = "block-selected"; blockSet[6].className = "block-selected"; blockSet[7].className = "block-selected";
.block-default { width: 100px; height: 50px; background-color: green; border: 1px solid red; padding: 10px; } .block-selected { width: 100px; height: 50px; background-color: blue; border: 1px solid white; padding: 10px; }
<div class="block-default">BLOCK1</div> <div class="block-default">BLOCK2</div> <div class="block-default">BLOCK3</div> <div class="block-default">BLOCK4</div> <div class="block-default">BLOCK5</div> <div class="block-default">BLOCK6</div> <div class="block-default">BLOCK7</div> <div class="block-default">BLOCK8</div>
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