Создание аккордеона, направить на путь правильный

275
27 ноября 2021, 20:10

Есть такая структура в PUG:

.table-wrap
     .table-block
         .services__block.services__title.services__btn Нажать кнопку
         .table-hidden
              table.services__table
     .table-block
         .services__block.services__title.services__btn Телеграм боты
         .table-hidden

JS:

 document.querySelector('.table-wrap').addEventListener('click', function (event) {
    var block = event.target.closest('.table-block');
    if (block) {
      var elem = block.querySelector('.table-hidden');
      if (elem.classList.contains('active')) {
        elem.style.height = getComputedStyle(elem).height;
        elem.classList.remove('active');
        getComputedStyle(elem).height; // reflow
        elem.style.height = '';
      } else {
        elem.classList.add('active');
        var h = getComputedStyle(elem).height;
        elem.style.height = '0';
        getComputedStyle(elem).height; // reflow
        elem.style.height = h;
        setTimeout(function () { elem.style.height = '' }, 1000); // Когда закончится анимация
      }
    }
  });

Потому что когда открывается таблица, даётся класс active, а если нажму на таблицу, он уберёт его снова. Сидел часа 2 над этим.

Всё вроде как хорошо, но мне нужно, чтобы только при нажатии на кнопку .services__btn добавлялось в .table-hidden класс .active А у меня не получается написать из этого код. И чтобы первая кнопка добавляла только первому .table-hidden класс .active, можно сказать как аккордеон.

Answer 1

Вы хотите чтобы регистрировалось нажатие только на кнопку .service__btn - тогда стоит сделать условием начала работы именно это: event.target.closest('.services__btn')
В вашем коде вы сделали условием нажатие на любой элемент блока.

Я добавил свои фрагменты кода чтобы улучшить анимацию (возможно она у вас реализована в стилях - тогда исключите пожалуйста лишнее). Пример с PUG можно посмотреть здесь: https://codepen.io/ilya-lokalin/pen/bGGXzmX

Ниже тот же пример с HTML:

document.querySelector('.table-wrap').addEventListener('click', function (event) { 
  const target  = event.target; 
  const block   = target.closest('.table-block'); 
   
   
  // Проверяем что нажата именно кнопка 
  if (target.closest('.services__btn')) { 
     
    if (block) { 
      const elem = block.querySelector('.table-hidden'); 
       
      if (elem.classList.contains('active')) { 
        elem.classList.remove('active'); 
        let elementHeight = parseInt(getComputedStyle(elem).height); 
         
 
        //Анимация скрытия 
        elem.style.opacity = '0'; 
        let stepDown = function () { 
          elem.style.height = elementHeight + 'px'; 
           
          if (elementHeight-- > 0) { 
            setTimeout(stepDown, 10); 
          }  
        } 
        setTimeout(stepDown, 10); 
         
      } else { 
        elem.classList.add('active'); 
        const heightLimit = parseInt(block.dataset.height); 
        let elementHeight = 0; 
         
 
        //Анимация показа блока 
        let stepUp = function () { 
          elem.style.height = elementHeight + 'px'; 
    
          if (elementHeight++ < heightLimit) { 
            setTimeout(stepUp, 10); 
          } else { 
            elem.style.opacity = '1'; 
          } 
        } 
        setTimeout(stepUp, 10); 
         
        } 
     } 
  } 
});
.services__btn { 
  cursor: pointer; 
}
<div class="table-wrap"> 
    <div class="table-block" data-height="18px"> 
        <div class="services__block services__title services__btn">Нажать кнопку</div> 
        <div class="table-hidden active"> 
            <table class="services__table">Какой-то текст</table> 
        </div> 
    </div> 
    <div class="table-block" data-height="18px"> 
        <div class="services__block services__title services__btn">Телеграм боты</div> 
        <div class="table-hidden active">И тут текст</div> 
    </div> 
</div>

READ ALSO
Правильное ли решение этой задании таким образом?

Правильное ли решение этой задании таким образом?

Создайте функцию конструктор Calculator, которая создаёт «расширяемые» объекты калькулятораРеализуйте метод calculate(str), который принимает строку...

191
Confirm с альтернативными ответами в JavaScript

Confirm с альтернативными ответами в JavaScript

Возможно ли сделать confirm где кнопки будут содержать не 'ОК' и 'Отмена', а другие значения, к примеру 'Да' и 'Нет'?

83
Удалить все элементы содержание класс

Удалить все элементы содержание класс

Начал изучать чистый javascriptПредставим проверку формы, где ошибки выводится под каждым тегом input элементом <span class="error"></span>

104
Удаление элемента массива и выдача случайного элемента в строку

Удаление элемента массива и выдача случайного элемента в строку

Я совсем новичок и имею проблемы с синтаксисом и русским языкомПомогите сделать чтобы программа загружала список имен из массив и при нажатии...

209