1

I am creating a accordion with use of pure JavaScript. Initailly I have shown content of only first section. Then by using JavaScript I am showing content on clicking sections.

This works well but when I click on section1 it does not hide because active class is still there.

<!DOCTYPE html>
<html>
<head>
<style>
.main {
    background-color: #eee;
    width:350px;
    color: #444;   
    padding: 18px;  
    border: none;
    text-align: left;
    font-size: 15px;

}

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

div.panel {
    padding: 0 18px;
   background-color: white;
   display:none;
   width:350px;


}
.active{
    display: block !important;

}

div.panel.show {
    display: block;
}
div.panel.hide {
    display: none;
}
</style>
</head>
<body>
<div class="main">Section 1</div>
<div class="panel active">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="main">Section 2</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<div class="main">Section 3</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<script>
var acc = document.getElementsByClassName("main");
var i;
for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function(){    
      this.nextElementSibling.classList.toggle("show");     
  }
}
</script>

</body>
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186
Passionate Coder
  • 7,154
  • 2
  • 19
  • 44

4 Answers4

2

You can try something like this:

Logic:

  • Check if current clicked section is open or close and save it. This will be use to toggle state.
  • Hide all open sections.
  • If current section is visible, don't do anything. If not, show it.

JSFiddle

function registerEvents() {
  var sections = document.querySelectorAll(".main");
  for (var i = 0; i < sections.length; i++) {
    sections[i].addEventListener("click", toggleSection)
  }
}

function toggleSection(e) {
  var ele = e.target.nextElementSibling;
  var isNotVisible = ele.className.indexOf("active") < 0;
  hideAllPanels();
  if (isNotVisible)
    addClass(ele, "active");
}

function hideAllPanels() {
  var panels = document.querySelectorAll(".panel.active");
  for (var i = 0; i < panels.length; i++) {
    panels[i].className = panels[i].className.replace("active", "");
  }
}

function addClass(el, _class) {
  el.className += " " + _class;
}

(function init() {
  registerEvents();
})()
.main {
  background-color: #eee;
  width: 350px;
  color: #444;
  padding: 18px;
  border: none;
  text-align: left;
  font-size: 15px;
}
.main.active,
.main:hover {
  background-color: #ddd;
}
div.panel {
  padding: 0 18px;
  background-color: white;
  display: none;
  width: 350px;
}
.active {
  display: block !important;
}
div.panel.show {
  display: block;
}
div.panel.hide {
  display: none;
}
<div class="main">Section 1</div>
<div class="panel active">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="main">Section 2</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<div class="main">Section 3</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

Note: I have taken leisure to updated your code.

Rajesh
  • 24,354
  • 5
  • 48
  • 79
1

After checking if the element in question has a class of active within the loop, try removing the active class on that element if it does. Note, I've added an id to the first panel for this example.

var acc = document.getElementsByClassName("main");
var i;
for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function(){   
      var active = document.getElementById("one").nextElementSibling;
      if(active.classList.contains("active") == true) {
        active.classList.remove("active");
      }
      this.nextElementSibling.classList.toggle("show");   
  }
}
.main {
    background-color: #eee;
    width:350px;
    color: #444;   
    padding: 18px;  
    border: none;
    text-align: left;
    font-size: 15px;

}

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

div.panel {
    padding: 0 18px;
   background-color: white;
   display:none;
   width:350px;


}
.active{
    display: block !important;

}

div.panel.show {
    display: block;
}
div.panel.hide {
    display: none;
}
<div id="one" class="main">Section 1</div>
<div class="panel active">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="main">Section 2</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<div class="main">Section 3</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
David Wilkinson
  • 5,060
  • 1
  • 18
  • 32
  • Note that in the initial run, you have to click twice to get the first panel closed. Not sure if that's the desired effect the OP would like to achieve. – Wracker Jun 15 '16 at 08:39
  • @Wracker Well spotted, thanks - I didn't notice that. I'll revise and see if I can make it better. – David Wilkinson Jun 15 '16 at 08:40
1

why don't you just give your first panel class show instead of active? active class seems redundant in your code.

code for the first panel:

<div class="panel show">
apieceofbart
  • 2,048
  • 4
  • 22
  • 30
1

If you're to use the active class to show the currently opened panel, then you have to also handle it's removal once the user clicks on other panels.

The code below also ensures that there can only be one active panel. All the others will be closed. ( If you don't like the behavior , simply remove the for-loop. )

<!DOCTYPE html>
<html>
<head>
<style>
.main {
    background-color: #eee;
    width:350px;
    color: #444;   
    padding: 18px;  
    border: none;
    text-align: left;
    font-size: 15px;

}

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

div.panel {
    padding: 0 18px;
   background-color: white;
   display:none;
   width:350px;


}
.active{
    display: block !important;
}

div.panel.show {
    display: block;
}
div.panel.hide {
    display: none;
}
</style>
</head>
<body>
<div class="main">Section 1</div>
<div class="panel active">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="main">Section 2</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<div class="main">Section 3</div>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<script>
var acc = document.getElementsByClassName("main");
var i;
for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function(){
  var el_id = this.innerHTML;
  if( ! this.nextElementSibling.classList.contains("active") ){
   this.nextElementSibling.classList.add("active");
   this.nextElementSibling.classList.add("show");
  }else{
   this.nextElementSibling.classList.remove("active");
   this.nextElementSibling.classList.remove("show");
  }

  for( var el = 0; el < acc.length; el++ ){
   if( acc[el].innerHTML != el_id ){
    if(acc[el].nextElementSibling.classList.contains("active")){
     acc[el].nextElementSibling.classList.remove("active");
     acc[el].nextElementSibling.classList.remove("show");
    }
   }
  }
 }
}
</script>

</body>
</html>
Wracker
  • 589
  • 10
  • 32