Home > OS >  Accordion class not removing correctly with javascript when object is closed
Accordion class not removing correctly with javascript when object is closed

Time:11-08

Not the best with javascript and I'm currently stuck on something. I've managed to put an accordion together that expands and collapses with an :after icon that transforms when the object is opened. It also only allows for one accordion to be open at a time which is what is needed.

My issue is that the :after icon is not functioning correctly because once the "active" class is added, it only gets removed if another object is opened, not if the same object is closed. Does anyone have a solution that could fix this? I need the class to be removed if another accordion is opened, as well as if the object is clicked again to close it.

As mentioned above I'm not the best with JS and i've really only achieved what I have with this accordion from other answers I've found on here. Here is my current code. Any help is greatly appreciated!

Javascript

var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i  ) {
acc[i].addEventListener("click", function() {

var panel = this.nextElementSibling;
if (panel.style.maxHeight){
  panel.style.maxHeight = null;
} else {
  let active = document.querySelectorAll(".accordion-div .accordion.active");
  for(let j = 0; j < active.length; j  ){
    active[j].classList.remove("active");
    active[j].nextElementSibling.style.maxHeight = null;
  }
  this.classList.toggle("active");
  panel.style.maxHeight = panel.scrollHeight   "px";
}
});
}

HTML

<div class="accordion-div">
<h5 class="accordion">Heading</h5>
<div class="panel">
<p>Some Text</p>
<h5 class="accordion">Heading 2</h5>
<div class="panel">
<p>Some Text</p>
<h5 class="accordion">Heading 3</h5>
<div class="panel">
<p>Some Text</p>
</div>
</div>

CSS

h5.accordion {
  cursor: pointer;
  padding: 25px!important;
  padding-left:2px!important;
  width: 100%;
  line-height:13px;
  text-align: left;
  outline: none;
  transition: 0.4s;
  font-size:13px!important;
  vertical-align:center;
  font-family:"Avenir Next", sans-serif;
  font-weight:300;
  margin:0;
  margin-top:2px;
  border-bottom:0!important;
}

h5.accordion:after {
  content: '\002B';
  line-height:13px;
  font-size:22px;
  float: right;
  color:#5f5f5f;
  margin-left: 5px;
  transition: transform .5s;
  transform-origin: 50% 60%;
}

.active:after {
  transform: rotate(-225deg);
}

.panel {
  padding: 0 2px;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
  border-bottom:solid 1px #f1f1f1;
}

CodePudding user response:

There was a typo that you were not closing div for your headings in your HTML please check the snippet, Also to open and close, I have added a line of JS to first remove the active class if present and then toggle based on this

Please run the snippet and see

var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i  ) {
acc[i].addEventListener("click", function() {
this.classList.remove("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight){
  panel.style.maxHeight = null;
} else {
  let active = document.querySelectorAll(".accordion-div .accordion.active");
  for(let j = 0; j < active.length; j  ){
    active[j].classList.remove("active");
    active[j].nextElementSibling.style.maxHeight = null;
  }
  this.classList.toggle("active");
  panel.style.maxHeight = panel.scrollHeight   "px";
}
});
}
h5.accordion {
  cursor: pointer;
  padding: 25px!important;
  padding-left:2px!important;
  width: 100%;
  line-height:13px;
  text-align: left;
  outline: none;
  transition: 0.4s;
  font-size:13px!important;
  vertical-align:center;
  font-family:"Avenir Next", sans-serif;
  font-weight:300;
  margin:0;
  margin-top:2px;
  border-bottom:0!important;
}

h5.accordion:after {
  content: '\002B';
  line-height:13px;
  font-size:22px;
  float: right;
  color:#5f5f5f;
  margin-left: 5px;
  transition: transform .5s;
  transform-origin: 50% 60%;
}

.active:after {
  transform: rotate(-225deg);
}

.panel {
  padding: 0 2px;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
  border-bottom:solid 1px #f1f1f1;
}
javascript
jquery
<div class="accordion-div">
<h5 class="accordion">Heading</h5>
<div class="panel">
<p>Some Text</p>
</div>
<h5 class="accordion">Heading 2</h5>
<div class="panel">
<p>Some Text</p>
</div>
<h5 class="accordion">Heading 3</h5>
<div class="panel">
<p>Some Text</p>
</div>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

First, remove all active classes when the h5 tag is clicked

const removeActiveClasses = (e) => {
    const target = e.targrt || e.currentTarget;
    const active = target.querySelector(".accordion.active");
    active.classList.remove("active");
}

Then you need to activate the current element

const activeElement = (e) => {
    const target = e.target.nextElementSibling;
    target.classList.add("active");
}

At the End

const accordion = e => {
    removeActiveClasses(e);
    activeElement(e);
}

for (i = 0; i < acc.length; i  ) {
    acc[i].addEventListener("click", accordion);
}

Notice: You do not need to use a loop because you only want one active element

  • Related