首页 > 解决方案 > Javascript - 选择所有复选框并更改多个类功能

问题描述

我遇到了一个我不确定正确答案的问题。我有一个 javascript 代码,我想在其中选中页面上的每个复选框,并将.absent CSS 类替换为.present对于每个具有类.tile.absent的元素。我所看到的是这可行,但用户必须重复调用该函数才能选择页面上的每个适用元素。为什么它不是第一次选择每个元素?

如果第一段没有意义,我的目标是使功能按如下方式工作:当用户单击“标记所有存在”时,页面上的每个图块都应亮起紫色。

密码: https ://codepen.io/dansbyt/pen/yLVzJog

Javascript:

function selectall(arg){
  if (arg == 'selectmulti') {var check = document.getElementsByClassName("clickable");}
  if (arg == 'attendance') {
    var check = document.getElementsByTagName('input');
    var tile = document.getElementsByClassName('tile absent');
    for(i=0; i<tile.length; i++){
      tile[i].classList.add('present');
      tile[i].classList.remove('absent');
    }
  }
  for(i=0; i<check.length; i++){
    if(check[i].type=='checkbox'){
      check[i].checked=true;
    }
  }
}


function deselectall(arg){
  if (arg == 'attendance') {var uncheck = document.getElementsByTagName('input');}
  if (arg == 'selectmulti') {var uncheck = document.getElementsByClassName("clickable");}
  for(i=0; i<uncheck.length; i++){
    if(uncheck[i].type=='checkbox'){
      uncheck[i].checked=false;
    }
  }
}

HTML:

<div id='grid'>
  <input type='checkbox' id='1' value='1' disabled>
  <label for='1'>
    <div class='tile absent'>
      <img class='tile_pic' src='../resources/pics/default.png'>
      <div class='tile_title'>John Doe</div>
    </div>
  </label>
  
  <input type='checkbox' id='2' value='2' disabled>
  <label for='2'>
    <div class='tile absent'>
      <img class='tile_pic' src='../resources/pics/1/22.jpg'>
      <div class='tile_title'>Kennedy Adam</div>
    </div>
  </label>
  
  <input type='checkbox' class='clickable' id='3' value='3' disabled>
  <label for='3'>
    <div class='tile present'>
      <img class='tile_pic' src='../resources/pics/1/19.jpg'>
      <div class='tile_title'>Sawyer Tom</div>
    </div>
  </label>

  <input type='checkbox' id='4' value='4' disabled>
  <label for='4'>
    <div class='tile absent'>
      <img class='tile_pic' src='../resources/pics/1/22.jpg'>
      <div class='tile_title'>Linny Baker</div>
    </div>
  </label>

  <input type='checkbox' class='clickable' id='5' value='5' disabled>
  <label for='5'>
    <div class='tile present'>
      <img class='tile_pic' src='../resources/pics/1/19.jpg'>
      <div class='tile_title'>Patrick MeLoy</div>
    </div>
  </label>
  
  <input type='checkbox' id='6' value='6' disabled>
  <label for='6'>
    <div class='tile absent'>
      <img class='tile_pic' src='../resources/pics/default.png'>
      <div class='tile_title'>Cyrus Everdeen</div>
    </div>
  </label>
  
  <input type='checkbox' id='7' value='7' disabled>
  <label for='7'>
    <div class='tile absent'>
      <img class='tile_pic' src='../resources/pics/1/22.jpg'>
      <div class='tile_title'>Samuel Adams</div>
    </div>
  </label>
  
  <input type='checkbox' class='clickable' id='8' value='8' disabled>
  <label for='8'>
    <div class='tile present'>
      <img class='tile_pic' src='../resources/pics/1/19.jpg'>
      <div class='tile_title'>Robert Paine</div>
    </div>
  </label>

  <input type='checkbox' id='9' value='9' disabled>
  <label for='9'>
    <div class='tile absent'>
      <img class='tile_pic' src='../resources/pics/1/22.jpg'>
      <div class='tile_title'>Thomas Preston</div>
    </div>
  </label>

  <input type='checkbox' class='clickable' id='10' value='10' disabled>
  <label for='10'>
    <div class='tile present'>
      <img class='tile_pic' src='../resources/pics/1/19.jpg'>
      <div class='tile_title'>Trae Smith</div>
    </div>
  </label>
</div>
<br><br>
        <div class="attendance">
          <ul>
            <ul class="left">
              <li> <a class="deselectall" onclick="deselectall('attendance')"> Mark All Absent </a> </li>
              <li> <a class="selectall" onclick="selectall('attendance')"> Mark All Present </a> </li>
            </ul>
        </div>

CSS:

body {margin: 120px 25px 55px 25px}

#grid {
  max-width: 1880px;
  margin: 0 auto;
  display: grid;
  grid-gap: 20px;}

.tile {
  width: 125px; height: 165px;
  font-size: 0.9rem;
  background-color: white;
  border-radius: 4%;
  overflow: hidden;
  text-align: center;
  box-shadow: 3px 4px #CECECE}
  .tile img{max-width: 100%; max-height: 100%; display: block;}
  .tile:hover:not(.absent) {background-color: #BFB3E6; box-shadow: 3px 4px #9E999E; cursor: grab; transform: scale(1.05);}

.absent {filter: grayscale(100%); color: gray;}

.tile_pic{
  width: 125px;
  height: 125px;
  object-fit: cover;}

.tile_title {
  margin-top: 10px;
  font-family: 'Rubik', sans-serif;}

#grid input[type=checkbox] {display: none;}
#grid input:checked + label .tile{background-color: #9885D6; box-shadow: 3px 4px #9E999E}

@media (min-width: 430px) {#grid { grid-template-columns: repeat(5, 1fr); }}
@media (min-width: 660px) {#grid { grid-template-columns: repeat(6, 1fr); }}
@media (min-width: 890px) {#grid { grid-template-columns: repeat(7, 1fr); }}
@media (min-width: 1120px) {#grid { grid-template-columns: repeat(8, 1fr); }}
@media (min-width: 1350px) {#grid { grid-template-columns: repeat(9, 1fr); }}
@media (min-width: 1580px) {#grid { grid-template-columns: repeat(10, 1fr); }}

标签: javascriptcss

解决方案


随着循环的每次迭代,getElementsByClassName结果越来越小,因为您修改的每个元素都被排除在外。

getElementsByClassName 返回对象被视为“实时集合”,因此对 DOM 的任何更改都可能实时影响此函数的结果。

将其更改为:

document.getElementsByClassName('tile absent')

对此:

document.querySelectorAll('.tile.absent')

为了让它按预期工作(一个初始查询来获取所有元素,然后修改不会影响集合)。

MDN有一个关于这个看似奇怪的功能的有用信息简介:

警告:这是一个实时的 HTMLCollection。DOM 中的更改将在更改发生时反映在数组中。如果此数组选择的元素不再符合选择器的条件,它将自动被删除。出于迭代目的,请注意这一点。


推荐阅读