@Smirator

Почему не работает аккордеон в таблице?

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

Важно, реализация именно для таблицы. Стандартный аккордеон тут не подойдет.
<table>
               <tr>
                 <td><button class="panel" id="elem-one">Тариф 1</button></td>
                 <td>100 р</td>
                 <td>250 р</td>
                 <td>300 р</td>
               </tr>
               <tr>
                 <td id="panel-one" class="d-n panel-block" colspan="4"><p>Информация о тарифе-1</p></td>
               </tr>

               <tr>
                 <td><button class="panel" id="elem-two">Тариф 2</button></td>
                 <td>200 р</td>
                 <td>450 р</td>
                 <td>600 р</td>
               </tr>
               <tr>
                 <td id="panel-two" class="d-n panel-block" colspan="4"><p>Информация о тарифе -2</p></td>
               </tr>
</table>


.d-n {
  display: none;
}

.active {
  display: table-cell;
  animation: ani 1.5s forwards;
}

.changing-icon:after {
    content: "\2796";
}


Это работает:
document.getElementById('elem-one').onclick = function() {
  document.getElementById('panel-one').classList.toggle('active');
  if(document.getElementById('panel-one').classList.contains('active')){
    document.getElementById('elem-one').classList.add('changing-icon');
  } else {
    document.getElementById('elem-one').classList.remove('changing-icon');
  }
}

document.getElementById('elem-two').onclick = function() {
  document.getElementById('panel-two').classList.toggle('active');
  if(document.getElementById('panel-two').classList.contains('active')){
    document.getElementById('elem-two').classList.add('changing-icon');
  } else {
    document.getElementById('elem-two').classList.remove('changing-icon');
  }
}


Это нет:
let panels = document.getElementsByClassName("panel");
let i;

for (i = 0; i < panels.length; i++) {
  panels[i].addEventListener("click", function() {
    this.classList.toggle("active");
    let panel = this.parentNode.parentNode.nextSibling; //Как понимаю, нужно достучаться до родителя и к последующей строке. (btn>td>tr).  

    if(this.classList.contains('active')){
         this.classList.add('changing-icon');
    } else {
       this.classList.remove('changing-icon');
    }
   if (this.classList.contains('active')) {
       panel.style.display = "table-cell";
    } else {
      panel.style.display = "none";
    }
  });
}
  • Вопрос задан
  • 87 просмотров
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
что делаю не так?

Всё делаете не так.

Зачем переключаете класс active на кнопке? Его у элемента с классом d-n переключать надо - вместо той ерунды с изменением стилей напрямую. Кстати, а кому вы пытаетесь назначить style.display = 'table-cell'? Если идти от кнопки parent-parent-next (вместо того, чтобы несколько раз дёргать parentNode, следует использовать метод closest) - это будет (не будет, погуглите, в чём разница между nextSibling и nextElementSibling) строка, а не ячейка - так что перенесите-ка класс d-n на один уровень выше. Зачем создавать каждой кнопке индивидуальный обработчик? Достаточно одного на всех, создавайте его вне цикла. Наконец, у classList.toggle есть второй параметр, не надо им пренебрегать.

Исправляем:

document.querySelectorAll('.panel').forEach(n => n.addEventListener('click', onClick));

function onClick() {
  const panel = this.closest('tr').nextElementSibling;
  const isActive = !panel.classList.contains('active');
  panel.classList.toggle('active', isActive);
  this.classList.toggle('changing-icon', isActive);
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы