Accordion

Simple Accordion in Vanilla JS

by mrjordy

HTML

<div class="accordionMenuBar">
<div class="accordionMenu1 closeAll"><button onclick="closeallFunction()">close all</button></div>
<div class="accordionMenu2 expandAll">expand all</div>
<div class="accordionMenu3 personType1">person type 1</div>
<div class="accordionMenu4 personType2">person type 2</div>
<div class="accordionMenu5 personType3">person type 3</div>
</div>
<div class="accordionTrigger">H2 thing 1</div>
<div class="accordionPane show">
  <p>text</p>
</div>

<div class="accordionTrigger">H2 thing 2</div>
<div class="accordionPane show">
  <p>text</p>
</div>

<div class="accordionTrigger">H2 thing 3</div>
<div class="accordionPane show">
  <p>text</p>
</div>

CSS

/* Style the buttons that are used to open and close the accordion panel */

.accordionTrigger {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  text-align: left;
  border: none;
  outline: none;
  transition: 0.4s;
}


/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */

.accordionTrigger.active,
.accordionTrigger:hover {
  background-color: #ddd;
}

.accordionPane {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: 0.6s ease-in-out;
  opacity: 0;
}


/* The "show" class is added to the accordion panel when the user clicks on one of the buttons. This will show the panel content */

.accordionPane.show {
  opacity: 1;
  max-height: 500px;
}

JavaScript

// Event delegation
document.addEventListener("click", delegate(accFilter, accHandler));

// close all
function closeallFunction() {
  var element = document.getElementByClass("accordionPane");
  element.classList.add("show");
}

// Common helper for event delegation.
function delegate(criteria, listener) {
  return function(e) {
    var el = e.target;
    do {
      if (!criteria(el)) {
        continue;
      }
      e.delegateTarget = el;
      listener.call(this, e);
      return;
    } while ((el = el.parentNode));
  };
}

// Custom filter to check for required DOM elements
function accFilter(elem) {
  return (elem instanceof HTMLElement) && elem.matches(".accordionTrigger");
}

// Custom event handler function
function accHandler(e) {
  var acc = e.delegateTarget;
  acc.classList.toggle("active");
  acc.nextElementSibling.classList.toggle("show");

  var otherAccordions = getSiblings(acc.nextElementSibling, '.accordionPane');
  otherAccordions.forEach(function(otherAcc) {
    otherAcc.classList.remove('show');
    otherAcc.previousElementSibling.classList.remove("active");
  })
}