EdVinson
EdVinson

Reputation: 15

Collapse an accordion menu

I have this simple collapsible menu on www.keokuk.com I would like for the previous menu to close when you click on the next one.

this is the javascript:

<script>
    var coll = document.getElementsByClassName("collapsible");
    var i;

    for (i = 0; i < coll.length; i++) {
      coll[i].addEventListener("click", function () {
        this.classList.toggle("active");
        var content = this.nextElementSibling;
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";

        }
      });
    }
  </script>

Upvotes: 0

Views: 140

Answers (2)

zer00ne
zer00ne

Reputation: 44086

Details are commented in example

// Collect all .switch into an array
const switches = [...document.querySelectorAll(".switch")];

// Bind each .switch to the click event
switches.forEach(s => s.addEventListener("click", openClose));

// Event handler passes Event Object as default
function openClose(event) {
  // Reference the tag proceeding clicked tag
  const content = this.nextElementSibling;
  // Get the height of content
  let maxHt = content.scrollHeight + 'px';
  // Find the index position of clicked tag
  let index = switches.indexOf(this);
  // The clicked tag will toggle .active class
  this.classList.toggle('active');
  // Remove .active class from all .switch
  switches.forEach((btn, idx) => {
    /*
    If current index does NOT equal index of 
    clicked tag...
    ...remove .active 
    */
    if (idx != index) {
      btn.classList.remove('active');
    }
  });
  /*
  If clicked has .active class...
  ...set style property of max-height using CSS variables
  */
  if (this.classList.contains('active')) {
    content.style.setProperty('--maxH', maxHt + 'px');
  } else {
    content.style.setProperty('--maxH', '0px');
  }
}
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box
}

:root {
  font: 300 1.5ch/1.2 'Segoe UI';
  --maxH: 0px;
}

body {
  width: 100%;
  min-height: 200%;
  padding: 15px;
}

header {
  width: max-content;
  margin: 10px 0 0;
  padding: 5px 10px;
  border: 3px ridge black;
  border-radius: 4px;
  background: #aaa;
  cursor: pointer;
}

section {
  position: relative;
  max-height: var(--maxH);
  margin: 0;
  padding: 5px 10px;
  border: 3px ridge black;
  border-radius: 4px;
  background: #ddd;
  opacity: 0;
  pointer-events: none;
}

.active+section {
  z-index: 1;
  opacity: 1.0;
}
<header class='switch'>Read more...</header>
<section>
  <p>Merchandise Morty, your only purpose in life is to buy &amp; consume merchandise and you did it, you went into a store an actual honest to god store and you bought something, you didn't ask questions or raise ethical complaints you just looked into
    the bleeding jaws of capitalism and said 'yes daddy please' and I'm so proud of you, I only wish you could have bought more, I love buying things so much Morty. Morty, you know outer space is up right? Are you kidding? I'm hoping I can get to both
    of them, Rick! And there's no evidence that a Latino student did it.</p>
</section>

<header class='switch'>Read more...</header>
<section>
  <p>Oh, I'm sorry Morty, are you the scientist or are you the kid who wanted to get laid? Why don't you ask the smartest people in the universe, Jerry? Oh yeah you can't. They blew up. Looossseeerrrrr. I am not putting my father in a home! He just came
    back into my life, and you want to, grab him and, stuff him under a mattress like last month's Victoria's Secret?!
  </p>
</section>

Upvotes: 0

GregThB
GregThB

Reputation: 293

I worked on a solution on your website.

But it appears you set max-height manually in an other javascript function so you can just do the same thing in the commented line.

document.querySelectorAll('.collapsible').forEach(el => {
el.addEventListener('click', (e) => {
    document.querySelectorAll('.collapsible').forEach(e => {
        e.classList.remove('active');
        e.nextSibling.nextElementSibling.style.maxHeight = "0px";
    });

    e.target.classList.toggle('active');
    e.target.nextSibling.nextElementSibling.style.maxHeight =
        `${el.nextSibling.nextElementSibling.scrollHeight}px`;
    });
});

Upvotes: 1

Related Questions