Обновление от 04.10.18: Я обновил фрагмент, чтобы отразить изменения для всех, кто может наткнуться на эту ветку в поисках помощи. Существующие флажки и новые добавленные флажки открывают / закрывают меню.

var statusChangeMenu, activeList, itemCheckBox, activeItems;
statusChangeMenu = document.getElementById("status-change-menu");
activeList = document.getElementById("active-items");
itemCheckBox = activeList.getElementsByClassName("item-checkbox");
activeItems = activeList.getElementsByClassName("active-item-text");

function addNewItem(event) {
  event.preventDefault();
  activeList.insertAdjacentHTML("afterbegin", "\
<li class=\"item\">\
  <input class=\"item-checkbox\" type=\"checkbox\" name=\"checkbox\" />\
  <span class=\"active-item-text\"></span>\
  <button class=\"btn-complete\">complete</button>\
</li>");
  activeItems[0].textContent = document.getElementById("new-item-text").value;
}

document.getElementById("btn-add-item").addEventListener("click", addNewItem, false);
activeList.addEventListener("change", function() {
  var i, len;
  for (i = 0, len = itemCheckBox.length; i < len || (i = 0); ++i) {
    if (itemCheckBox[i].checked) {
      i = 40;
      break;
    }
  }
  statusChangeMenu.style.height = i + "px";
}, false);
*{
    margin: 0;
    padding: 0;
}
body{
    background-color: #393F4D;
}
header{
    background-color: #1D1E22;
    color: #FEDA6A;
    text-align: center;
    font-size: 10px;
}
main{
    background-color: #707070;
    max-width: 700px;
    margin: auto;
    margin-top: 20px;
    padding: 15px;
}
#status-change-menu{
    background-color: rgb(218, 123, 123);
    margin-top: 10px;
    height: 0px;
    overflow: hidden;
    transition: all .25s ease-in-out;
}
#status-change-menu>button>img{
    height: 40px;  
}
form{
    background-color: #D4D4DC;
    padding: 10px;
    text-align: right;
    box-shadow: 1px 1px 3px;
}
#new-item-text{
    width: 100%;
}
#btn-add-item{
    padding: 5px;
    box-shadow: 1px 1px 3px; 
}
.item-list-container{
    background-color: #D4D4DC;
    margin-top: 20px;
    box-shadow: 1px 1px 3px;
}
.item{
    background-color: rgb(165, 233, 222);
    list-style: none;
    display: grid;
    grid-template-columns: auto 1fr max-content;
    grid-template-rows: 30px;
    margin-top: 10px;
}
.item-checkbox{
    grid-column: 1/2; 
  width: 30px;
  margin:auto;
}
.active-item-text{
    grid-column: 2/3;
    background: rgb(252, 252, 252);
    overflow: hidden;
}
.btn-complete{
 grid-column: 3/4;
}
.item>input{
  height: 20px;
}
<body id="the-list">
    <header>
        <h1>The List V4</h1>
    </header>
    <main>
        <form action="#">
            <textarea name="textbox" id="new-item-text" cols="30" rows="1"></textarea>
            <button type="submit" id="btn-add-item">Add</button>
        </form>
        <div id="status-change-menu" class="change-menu">
          <h3>Status Change Menu</h3>
            <button class="btn-bar-hold">BTN1<img src="img/btn_hold.svg" alt=""></button>
            <button class="btn-bar-delete">BTN2<img src="img/btn_delete.svg" alt=""></button>
        </div>
        <div class="item-list-container">
            <ul id="active-items" class="item-list">
                <li class="item">
                  <input class="item-checkbox" type="checkbox" name="checkbox">
                  <span class="active-item-text">random text text random</span>
                  <button class="btn-complete">complete</button>
                </li>
                <li class="item">
                  <input class="item-checkbox" type="checkbox" name="checkbox">
                  <span class="active-item-text">random text text random</span>
                  <button class="btn-complete">complete</button>
                </li>
            </ul>
        </div>
    </main>
</body>

Я работаю над простым веб-приложением с контрольным списком, используя чистый HTML, CSS, javascript. Я застрял в одной части все выходные. Надеюсь, что кто-то сможет пролить свет на то, что я упускаю или делаю неправильно. Вот где я.

Моя цель

Каждый раз, когда элемент в контрольном списке (ul) выбирается (с помощью флажка), появляется скрытое меню с различными опциями для управления выбранным элементом (ами). Меню должно оставаться видимым, если установлен какой-либо из флажков в списке. Меню должно закрываться, если не отмечены флажки.

Где я застрял

Я могу заставить меню выдвигаться во время события «изменение» флажка, но я не могу заставить элемент меню реагировать после начального события изменения. Во время отладки также кажется, что элемент меню не реагирует на то, что флажок находится в состоянии «отмечен», а просто реагирует на изменение флажка в целом. Вот код JS, который у меня есть, но я безуспешно тестировал различные другие конфигурации.

Code Pen с полным кодом и фрагмент связанного кода JS ниже. Обновленный Codepen 04.10.18 https://codepen.io/skazx/pen/mzeoEO?

var itemCheckBox = document.querySelectorAll('input[type="checkbox"]')
var statusChangeMenu = document.getElementById("status-change-menu")

for(var i = 0 ; i < itemCheckBox.length; i++){
  itemCheckBox[i].addEventListener("change", function(){

    if (!itemCheckBox.checked)
    {statusChangeMenu.style.height = "40px";}
    else 
    {statusChangeMenu.style.height = "0px";}
  })}

Я прочитал несколько десятков разных сообщений и статей, но большинство из них были связаны с наличием только одного флажка или использованием jquery. Дайте мне знать, если вам понадобится дополнительная информация. Спасибо!

0
skaz 1 Окт 2018 в 22:58

2 ответа

Лучший ответ

itemCheckBox относится к NodeList возвращено querySelectorAll, а не отдельный элемент, поэтому говорить itemCheckBox.checked на самом деле не имеет смысла.

Вам следует проверить, установлен ли в списке любой флажок, который можно использовать с функцией .some(), например:

Вот рабочая демонстрация

for (var i = 0; i < itemCheckBox.length; i++) {
  itemCheckBox[i].addEventListener("change", function(event) {
    if (!event.target.checked) {
      statusChangeMenu.style.height = "40px";
    } else {
      statusChangeMenu.style.height = "0px";
    }
  });
}
var itemCheckBox = document.querySelectorAll('input[type="checkbox"]');
var statusChangeMenu = document.getElementById("status-change-menu");
function changeHandler (event) {
  // get the list of checkboxes in real time in case any were added to the DOM
  var checkboxes = document.querySelectorAll('input[type="checkbox"]');
  var anyChecked = [].some.call(checkboxes, function(checkbox) { return checkbox.checked; });
  // alternatively (instead of using .some()):
  // var anyChecked = false;
  // checkboxes.forEach(function (checkbox) {
  //   if (checkbox.checked) {
  //     anyChecked = true;
  //   }
  // });

  if (anyChecked) {
    statusChangeMenu.style.height = "40px";
  } else {
    statusChangeMenu.style.height = "0px";
  }
}
for (var i = 0; i < itemCheckBox.length; i++) {
  itemCheckBox[i].addEventListener("change", changeHandler);
}

for (var i = itemCheckBox.length; i < itemCheckBox.length + 2; i++) {
  // add some checkboxes dynamically
  var newCheckbox = document.createElement("input");
  var newLabel = document.createElement("label");
  newLabel.innerText = "Checkbox " + (i + 1);
  newCheckbox.type = "checkbox";
  // -- IMPORTANT-- bind event listener on dynamically added checkbox
  newCheckbox.addEventListener("change", changeHandler);
  newLabel.appendChild(newCheckbox);
  newLabel.appendChild(document.createElement("br"));
  document.body.appendChild(newLabel);
}
#status-change-menu {
  height: 0;
  background-color: red;
  overflow: hidden;
  color: white;
  font-weight: bold;
}
<div id="status-change-menu">I should be visible if any checkboxes are checked</div>
<label>Checkbox 1<input type="checkbox"/></label><br/>
<label>Checkbox 2<input type="checkbox"/></label><br/>
<label>Checkbox 3<input type="checkbox"/></label><br/>
2
mhodges 2 Окт 2018 в 16:06

Mhodges верен в том, что itemCheckBox является NodeList, а не отдельным элементом. Другая проблема заключается в том, что вы пытаетесь проверить, отмечен ли измененный флажок, и если это не так, вы закрываете меню. Как вы описали, это не то, что вам нужно.

Вам нужен другой способ проверить, все ли флажки сняты, прежде чем закрыть меню. Простой способ сделать это - это просто еще один внутренний цикл в функции onChange:

for(var i = 0 ; i < itemCheckBox.length; i++){
  itemCheckBox[i].addEventListener("change", function(){
    showMenu = false
    for(var j = 0; j < itemCheckBox.length; j++)
      {
        if(itemCheckBox[j].checked)
          showMenu = true
      }
    if (showMenu)
      {statusChangeMenu.style.height = "40px";} 
    else 
      {statusChangeMenu.style.height = "0px";}
})}

Вот модифицированный фрагмент кода.

2
Simcox 1 Окт 2018 в 20:18