Целевой конкретный класс div вместо nextElementSibling

#javascript

#javascript

Вопрос:

Я создаю супер простой аккордеон javascript. Вот как это выглядит в настоящее время.

 var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i  ) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.display === "block") {
      panel.style.display = "none";
    } else {
      panel.style.display = "block";
    }
  });
}  
 .container {
  display: block;
  margin-bottom: 24px;
}
.panel {
  padding: 0 18px;
  background-color: white;
  display: none;
  overflow: hidden;
}  
 <div class="container">
  <button class="accordion">Section 1</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 2</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 3</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>  

Вместо того, чтобы использовать целевую панель this.nextElementSibling; , я бы хотел указать на нее имя класса.

Я заменил this.nextElementSibling; на var panel = document.getElementsByClassName("panel"); .

 var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i  ) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = document.getElementsByClassName("panel");
    if (panel.style.display === "block") {
      panel.style.display = "none";
    } else {
      panel.style.display = "block";
    }
  });
}  
 .container {
  display: block;
  margin-bottom: 24px;
}
.panel {
  padding: 0 18px;
  background-color: white;
  display: none;
  overflow: hidden;
}  
 <div class="container">
  <button class="accordion">Section 1</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 2</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 3</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>  

Я ожидал, что моя настройка найдет класс .panel вместо следующего родственного, но я получаю сообщение об ошибке «Uncaught TypeError: не удается прочитать свойство ‘display’ неопределенного».

Что я здесь делаю не так?

Ответ №1:

getElementsByClassName возвращает HTML Collection значение, которое не имеет style свойства и .style.display является undefined

чтобы получить доступ к элементу, вам нужно будет выполнить document.getElementsByClassName("panel")[0] (или [1] , [2] …)

выполнение document.getElementsByClassName даст вам все элементы в документе, вам нужно выбрать parent нажатую кнопку и выполнить запрос по ней

 var parent = evt.target.parentElement;
var panel = parent.getElementsByClassName("panel")[0];
  

 var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i  ) {
  acc[i].addEventListener("click", function(evt) {
    this.classList.toggle("active");
    var parent = evt.target.parentElement;
    var panel = parent.getElementsByClassName("panel")[0];
    if (panel.style.display === "block") {
      panel.style.display = "none";
    } else {
      panel.style.display = "block";
    }
  });
}  
 .container {
  display: block;
  margin-bottom: 24px;
}
.panel {
  padding: 0 18px;
  background-color: white;
  display: none;
  overflow: hidden;
}  
 <div class="container">
  <button class="accordion">Section 1</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 2</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 3</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>  

Ответ №2:

Похоже, сейчас это работает.
Добавлено let в строке 3 и [i] в строке 6; строка 2 удалена.

 var acc = document.getElementsByClassName("accordion");
//var i;
for (let i = 0; i < acc.length; i  ) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = document.getElementsByClassName("panel")[i];
    if (panel.style.display === "block") {
      panel.style.display = "none";
    } else {
      panel.style.display = "block";
    }
  });
}  
 .container {
  display: block;
  margin-bottom: 24px;
}
.panel {
  padding: 0 18px;
  background-color: white;
  display: none;
  overflow: hidden;
}  
 <div class="container">
  <button class="accordion">Section 1</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 2</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>

<div class="container">
  <button class="accordion">Section 3</button>
  <div class="panel">
    <p>Lorem ipsum...</p>
  </div>
</div>