Проверка Javascript все флажки установлены

#javascript #html

Вопрос:

У меня двойная проблема, которая связана с моим относительным незнанием Javascript. Я работаю над тем, чтобы понять основы, так что это должно быть простое решение, которое я просто не улавливаю.

Желаемый конечный результат:

  1. Если щелкнуть каждый флажок на странице, класс «selectall» должен быть скрыт, а класс «hideall» должен быть виден.
  2. Если установлен КАКОЙ-либо флажок, кнопки «посещаемость» и «действие» должны быть зелеными, кнопка «случайный» должна быть серой. (Противоположные цвета, если на странице не установлены флажки)
  3. Если я использую функцию «selectAll ()», должны применяться приведенные выше правила цвета.

Проблемы

  1. класс «selectall» не исчезает, если выбраны все поля.
  2. Если я в настоящее время использую функцию «selectAll ()», кнопки не становятся зелеными.

Мое понимание проблемы

Что касается проблемы № 1, я понятия не имею о причине проблемы. Что касается проблемы № 2, я получаю ошибку TypeError: null is not an object (evaluating 'termsCheckBox.closest('form').querySelectorAll') , которая заставляет меня полагать, что проблема связана с функцией «selectAll ()», которая не находится внутри тега HTML-формы. Из — за структуры страницы я не могу включить это в тег формы, и я не уверен, что есть какие-либо обходные пути.

Пожалуйста, помогите мне понять, что происходит не так и как это исправить! Если у вас есть какие-либо советы по очистке моего кода, я тоже буду признателен. Я учусь всему самостоятельно, поэтому я ценю ваш вклад и помощь!!

Живой Кодовый код https://codepen.io/dansbyt/pen/NWpXqev?editors=0110

Язык JavaScript:

 function chk(termsCheckBox){
      document.getElementById("attend").disabled = !termsCheckBox.closest('form').querySelectorAll("input[type=checkbox]:checked").length;
      if(document.getElementById("attend").disabled) {
        document.getElementById("attend").classList.remove("green-btn");
        document.getElementById("attend").classList.add("grey-btn");
        document.getElementById("action").classList.remove("green-btn");
        document.getElementById("action").classList.add("grey-btn");
        document.getElementById("random").classList.add("green-btn");
        document.getElementById("random").classList.remove("grey-btn");
      } 
      else {
        document.getElementById("attend").classList.add("green-btn");
        document.getElementById("attend").classList.remove("grey-btn");
        document.getElementById("action").classList.add("green-btn");
        document.getElementById("action").classList.remove("grey-btn");
        document.getElementById("random").classList.remove("green-btn");
        document.getElementById("random").classList.add("grey-btn");
      }
      var items = document.getElementsByTagName('input');
      for (var i = 0; i < items.length; i  ) {
        if (items[i].type == 'checkbox') {
          if (items[i].checked) {
            document.getElementsByClassName("selectall")[0].style.display = "none";
            document.getElementsByClassName("hideall")[0].style.display = "block";
          }
        }
      }
    }

// Below this line is not verified to work yet //

function selectAll() {
    var items = document.getElementsByTagName('input');
    for (var i = 0; i < items.length; i  ) {
        if (items[i].type == 'checkbox')
            items[i].checked = true;
    }
    document.getElementsByClassName("selectall")[0].style.display = "none";
    document.getElementsByClassName("hideall")[0].style.display = "block";
}

function hideAll() {
    var items = document.getElementsByTagName('input');
    for (var i = 0; i < items.length; i  ) {
        if (items[i].type == 'checkbox')
            items[i].checked = false;
    }
    document.getElementsByClassName("selectall")[0].style.display = "block";
    document.getElementsByClassName("hideall")[0].style.display = "none";
}
 

HTML:

 <div id='content'>
  <form id='grid'>
    <input type='checkbox' name='upid[]' id='292' value='292' onclick='chk(this);'>
    <label for='292'>
      <div class='tile absent'>
        <img class='tile_pic' src='../resources/pics/default.png'>
        <div class='tile_title'><b>Charlie</b></div>
      </div>
    </label>
    <input type='checkbox' name='upid[]' id='306' value='306' onclick='chk(this);'>
    <label for='306'>
      <div class='tile'>
        <img class='tile_pic' src='../resources/pics/students/68.jpg'>
        <div class='tile_title'><b>Marshall</b></div>
      </div>
    </label>
    <input type='checkbox' name='upid[]' id='107' value='107' onclick='chk(this);'>
    <label for='107'>
      <div class='tile'>
        <img class='tile_pic' src='../resources/pics/students/59.jpg'>
        <div class='tile_title'><b>Addix</b></div>
      </div>
    </label>
  </form>
</div>


<div id='bottombar'>
  
  <ul class="left">
    <li><a class="selectall" onclick='selectAll(); chk(this);'>Select All</a></li>
    <li><a class="hideall" style='display:none' onclick='hideAll(); chk(this);'>Select None</a></li>
  </ul>
  
  <ul class="right">
    <li><button id='attend' class="button grey-btn" disabled>Attendance</button></li>
    <li><button id='action' class="button grey-btn" disabled>Action</button></li>
    <li><button id='random' class="button green-btn">Random</button></li>
  </ul>

</div>
 

CSS:

 #grid {
  margin: 20px;
  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 {background-color: #C2CBB9; 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: #A3B195; 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); }}




/* Begin editing below here */
body {background-color: #F2F2F2;}

#content {
  position: absolute;
  width: 100vw; height: calc(100vh - 120px);
  top: 60px; left: 0;
  padding-top: 30px}

#bottombar {
  position: fixed;
  width: 100vw; height: 60px;
  bottom: 0; left: 0;
  padding: 4px;
  box-sizing: border-box;
  border-top: 2px solid darkgray;
  background-color: white;}

.right{float: right;}
.left{float: left;}

#bottombar ul{
  margin: 0;
  padding: 0;
  list-style-type: none}
  #bottombar li{float: left}

.selectall, .hideall {font-size: 20px; padding: 11px}

/* Customizes the global button design */
#bottombar .button {
  padding: 8px 24px;
  margin-right: 8px;
  font-size: 18px;
  border-radius: 26px}

 

Ответ №1:

You have this selector in chk() :

 termsCheckBox.closest('form').querySelectorAll("input[type=checkbox]:checked")
 

This will not work for elements outside the form (the buttons in the bottombar). Therefore you get the TypeError (null is not an object), there is no closest form.

Change the selector to:

 document.getElementById("grid").querySelectorAll("input[type=checkbox]:checked")
 

Следующая проблема заключается в том, что когда вы снимаете все элементы (не с помощью кнопки «Скрыть»), вы не нажимаете кнопку «скрыть все/ничего».

Вы пропустили эти две строки в своем if … случае в chk() :

 document.getElementsByClassName("selectall")[0].style.display = "block";
document.getElementsByClassName("hideall")[0].style.display = "none";
 

Или вы объединяете if — и else -дело вот так:

 const areAllSelected = grid.querySelectorAll("input[type=checkbox]:checked").length === grid.querySelectorAll("input[type=checkbox]").length;
document.getElementsByClassName("selectall")[0].style.display = areAllSelected ? "none" : "block";
document.getElementsByClassName("hideall")[0].style.display = areAllSelected ? "block" : "none";     
 
 function chk(termsCheckBox){
    const grid = document.getElementById("grid");
    document.getElementById("attend").disabled = !grid.querySelectorAll("input[type=checkbox]:checked").length;
    if(document.getElementById("attend").disabled) {
        document.getElementById("attend").classList.remove("green-btn");
        document.getElementById("attend").classList.add("grey-btn");
        document.getElementById("action").classList.remove("green-btn");
        document.getElementById("action").classList.add("grey-btn");
        document.getElementById("random").classList.add("green-btn");
        document.getElementById("random").classList.remove("grey-btn");
    } 
    else {
        document.getElementById("attend").classList.add("green-btn");
        document.getElementById("attend").classList.remove("grey-btn");
        document.getElementById("action").classList.add("green-btn");
        document.getElementById("action").classList.remove("grey-btn");
        document.getElementById("random").classList.remove("green-btn");
        document.getElementById("random").classList.add("grey-btn");
    }
    const areAllSelected = grid.querySelectorAll("input[type=checkbox]:checked").length === grid.querySelectorAll("input[type=checkbox]").length;
    document.getElementsByClassName("selectall")[0].style.display = areAllSelected ? "none" : "block";
    document.getElementsByClassName("hideall")[0].style.display = areAllSelected ? "block" : "none";      
}

// Below this line is not verified to work yet //

function selectAll() {
    var items = document.getElementsByTagName('input');
    for (var i = 0; i < items.length; i  ) {
        if (items[i].type == 'checkbox')
            items[i].checked = true;
    }
    document.getElementsByClassName("selectall")[0].style.display = "none";
    document.getElementsByClassName("hideall")[0].style.display = "block";
}

function hideAll() {
    var items = document.getElementsByTagName('input');
    for (var i = 0; i < items.length; i  ) {
        if (items[i].type == 'checkbox')
            items[i].checked = false;
    }
    document.getElementsByClassName("selectall")[0].style.display = "block";
    document.getElementsByClassName("hideall")[0].style.display = "none";
} 
 #grid {
  margin: 20px;
  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 {background-color: #C2CBB9; 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: #A3B195; 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); }}




/* Begin editing below here */
body {background-color: #F2F2F2;}

#content {
  position: absolute;
  width: 100vw; height: calc(100vh - 120px);
  top: 60px; left: 0;
  padding-top: 30px}

#bottombar {
  position: fixed;
  width: 100vw; height: 60px;
  bottom: 0; left: 0;
  padding: 4px;
  box-sizing: border-box;
  border-top: 2px solid darkgray;
  background-color: white;}

.right{float: right;}
.left{float: left;}

#bottombar ul{
  margin: 0;
  padding: 0;
  list-style-type: none}
  #bottombar li{float: left}

.selectall, .hideall {font-size: 20px; padding: 11px}

/* Customizes the global button design */
#bottombar .button {
  padding: 8px 24px;
  margin-right: 8px;
  font-size: 18px;
  border-radius: 26px} 
 <link rel="stylesheet" href="https://classcolonies.com/resources/style.css">

<div id='content'>
  <form id='grid'>
    <input type='checkbox' name='upid[]' id='292' value='292' onclick='chk(this);'>
    <label for='292'>
      <div class='tile absent'>
        <img class='tile_pic' src='https://classcolonies.com/resources/pics/default.png'>
        <div class='tile_title'><b>Charlie</b></div>
      </div>
    </label>
    <input type='checkbox' name='upid[]' id='306' value='306' onclick='chk(this);'>
    <label for='306'>
      <div class='tile'>
        <img class='tile_pic' src='https://classcolonies.com/resources/pics/students/68.jpg'>
        <div class='tile_title'><b>Marshall</b></div>
      </div>
    </label>
    <input type='checkbox' name='upid[]' id='107' value='107' onclick='chk(this);'>
    <label for='107'>
      <div class='tile'>
        <img class='tile_pic' src='https://classcolonies.com/resources/pics/students/59.jpg'>
        <div class='tile_title'><b>Addix</b></div>
      </div>
    </label>
  </form>
</div>


<div id='bottombar'>
  
  <ul class="left">
    <li><a class="selectall" onclick='selectAll(); chk(this);'>Select All</a></li>
    <li><a class="hideall" style='display:none' onclick='hideAll(); chk(this);'>Select None</a></li>
  </ul>
  
  <ul class="right">
    <li><button id='attend' class="button grey-btn" disabled>Attendance</button></li>
    <li><button id='action' class="button grey-btn" disabled>Action</button></li>
    <li><button id='random' class="button green-btn">Random</button></li>
  </ul>

</div> 

Кстати: вы можете просто использовать некоторые детали, когда используете classList.toggle() вот так:

 let condition = document.getElementById("attend").disabled;
document.getElementById("attend").classList.toogle("green-btn", !condition); // remove when condition is true, add when condition is false
document.getElementById("attend").classList.toogle("grey-btn", condition); // remove when condition is false, add when condition is true
 

Вы спасете if свое .

Комментарии:

1. Спасибо за вдумчивый ответ и комментарий, это помогает мне многое понять!! Есть только одна небольшая проблема с отображением выбора при одновременном изменении цвета кнопки… «Скрыть все» должно появиться только в том случае, если на странице нажаты ВСЕ флажки. Если даже один флажок не установлен, то должно отображаться «выбрать все». Есть какие-нибудь идеи, как это сделать?

2. @John Я отредактировал ответ. Взгляните на последние строки в chk() .

3. Я ОЧЕНЬ ценю вас! Большое вам спасибо за помощь.