className only changing every other class

2020-02-11 17:18发布

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;
 }

15条回答
爷、活的狠高调
2楼-- · 2020-02-11 17:46

This error is because you need to do

blockSet[0].className = 'block-selected'

You don't to write blockSet[1] , blockSet[2] ...

You can do:

for (var s=0;s<blockSetLength;s++) {
  blockSet[0].className = 'block-selected';
}
查看更多
Lonely孤独者°
3楼-- · 2020-02-11 17:46

Your error occur because .className return a live HTMLCollection. So when you do something like this:

blockSet[0].className = "block-selected";

Your collection blockSet[0] will become the blockSet[1]. So when you execute the line :

blockSet[1].className = "block-selected";

You not change the blockSet[1] you think but you change the starting blockSet[2].

So you can do this:

var blockSet = document.getElementsByClassName("block-default");
var blockSetLength = blockSet.length;
for(var i=0;i<blockSetLength;i++){
    blockSet[0].classList.add('block-selected'); //add the new class first
    blockSet[0].classList.remove('block-default'); //delete the old one
}

http://jsfiddle.net/94dqffa7/

I think it's the best way to do it. Because the classList.add() and classList.remove() will help you to change your class without eleminate the others class you have on your div (if you have some). Also, you need to add the new one before remove the old one or you will have the same problem as before.

查看更多
ゆ 、 Hurt°
4楼-- · 2020-02-11 17:49

The simplest way you can do this is by using the below code:

while(blockSetLength--){ 
    //this will change the class of n-1 dom object 
    blockSet[blockSetLength].className='block-selected';
}
查看更多
Bombasti
5楼-- · 2020-02-11 17:51

Instead of using getElementsByClassName(),
which returns a live HTMLCollection that will change as the classNames 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>

查看更多
甜甜的少女心
6楼-- · 2020-02-11 17:51

By assigning a value to .className you overwrite every class on that element. What you might want to take a look at is the .classList attribute.

Remove a class:

blockSet[0].classList.remove('block-default');

Add the new class:

blockSet[0].classList.add('block-selected');

A good point to start with, when your trying to do stuff, jQuery usually did for you, is http://youmightnotneedjquery.com/

查看更多
Luminary・发光体
7楼-- · 2020-02-11 17:51

You have already some good solutions.

I think that the best one is the one from Rick Hitchcock.

But a solution that I often use, to be safe when doing things like that, is to travel the collection backwards

var nmax = blockSet.length - 1;
for (var n=nmax; n>=0; n--) {
    blockSet[n].className = 'block-selected';
}

That isolates you from changes in the collection

查看更多
登录 后发表回答