accordion js

by AJIEKCEU

HTML

<!doctype html>
<html lang="ru">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>JavaScript Accordion - Example 1</title>
</head>

<body>

  <div class="accordion" style="max-width: 30rem; margin: 1rem auto 2rem;">
    <div class="accordion__item accordion__item_show">
      <div class="accordion__header">
        Заголовок 1
      </div>
      <div class="accordion__body">
        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tenetur et numquam optio, aut consequuntur iure magni
        tempore quo, velit, quos ipsum perferendis sit quidem sapiente voluptatem nesciunt rerum soluta amet.
      </div>
    </div>
    <div class="accordion__item">
      <div class="accordion__header">
        Заголовок 2
      </div>
      <div class="accordion__body">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Non earum deleniti recusandae placeat rem eius quod
        aliquid adipisci nemo alias debitis corporis pariatur quibusdam est, porro fuga id iure vero?
      </div>
    </div>
    <div class="accordion__item">
      <div class="accordion__header">
        Заголовок 3
      </div>
      <div class="accordion__body">
        Lorem ipsum dolor sit amet consectetur, adipisicing elit. Aliquid repellat dicta vel sapiente laudantium minima
        porro voluptatem nam, alias aliquam qui quasi eveniet odit fugiat eius aspernatur nesciunt veniam expedita!
      </div>
    </div>
  </div>

  <div class="accordion" style="max-width: 30rem; margin: 1rem auto;">
    <div class="accordion__item">
      <div class="accordion__header">
        Заголовок 4
      </div>
      <div class="accordion__body">
        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tenetur et numquam optio, aut consequuntur iure magni
        tempore quo, velit, quos ipsum perferendis sit quidem sapiente voluptatem nesciunt rerum soluta amet.
      </div>
    </div>
    <div...

CSS

body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
      font-size: 1rem;
      font-weight: 400;
      line-height: 1.5;
      color: #212529;
      text-align: left;
      background-color: #fff;
    }

    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }

    .accordion__item {
      margin-bottom: 0.5rem;
      border-radius: 0.25rem;
      box-shadow: 0 0.125rem 0.25rem rgb(0 0 0 / 15%);
    }

    .accordion__header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0.75rem 1rem;
      color: #fff;
      font-weight: 500;
      background-color: #0d6efd;
      border-top-left-radius: 0.25rem;
      border-top-right-radius: 0.25rem;
      cursor: pointer;
      transition: background-color 0.2s ease-out;
    }

    .accordion__header::after {
      flex-shrink: 0;
      width: 1.25rem;
      height: 1.25rem;
      margin-left: auto;
      background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
      background-repeat: no-repeat;
      background-size: 1.25rem;
      content: "";
    }

    .accordion__item_show .accordion__header::after {
      transform: rotate(-180deg);
    }

    .accordion__header:hover {
      background-color: #0b5ed7;
    }

    .accordion__item_hidden .accordion__header {
      border-bottom-right-radius: 0.25rem;
      border-bottom-left-radius: 0.25rem;
    }

    .accordion__body {
      padding: 0.75rem 1rem;
      overflow: hidden;
      background: #fff;
      border-bottom-right-radius: 0.25rem;
      border-bottom-left-radius: 0.25rem;
    }

   ...

JavaScript

class ItcAccordion {
      constructor(target, config) {
        this._el = typeof target === 'string' ? document.querySelector(target) : target;
        const defaultConfig = {
          alwaysOpen: true,
          duration: 350
        };
        this._config = Object.assign(defaultConfig, config);
        this.addEventListener();
      }
      addEventListener() {
        this._el.addEventListener('click', (e) => {
          const elHeader = e.target.closest('.accordion__header');
          if (!elHeader) {
            return;
          }
          if (!this._config.alwaysOpen) {
            const elOpenItem = this._el.querySelector('.accordion__item_show');
            if (elOpenItem) {
              elOpenItem !== elHeader.parentElement ? this.toggle(elOpenItem) : null;
            }
          }
          this.toggle(elHeader.parentElement);
        });
      }
      show(el) {
        const elBody = el.querySelector('.accordion__body');
        if (elBody.classList.contains('collapsing') || el.classList.contains('accordion__item_show')) {
          return;
        }
        elBody.style['display'] = 'block';
        const height = elBody.offsetHeight;
        elBody.style['height'] = 0;
        elBody.style['overflow'] = 'hidden';
        elBody.style['transition'] = `height ${this._config.duration}ms ease`;
        elBody.classList.add('collapsing');
        el.classList.add('accordion__item_slidedown');
        elBody.offsetHeight;
        elBody.style['height'] = `${height}px`;
        window.setTimeout(() => {
          elBody.classList.remove('collapsing');
          el.classList.remove('accordion__item_slidedown');
          elBody.classList.add('collapse');
          el.classList.add('accordion__item_show');
          elBody.style['display'] = '';
          elBody.style['height'] = '';
          elBody.style['transition'] = '';
          elBody.style['overflow'] = '';
        }, this._config.duration);
      }
      hide(el) {
        const elBody =...