简体   繁体   中英

Javascript accordion close header/panel if selected

I would like the accordion to close if the same header/panel is clicked, the function I've added hides the prior panel if a new header/panel is selected, but it won't hide itself.

Not looking to use any jquery, would like this to stay pure javascript

I've added another function hide() but haven't had any success yet, what would I need to change in the hide() for this to work, or could it all be done from the for loop?

 function accordion() { let acc = document.getElementsByClassName("accordion") let i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { hide() this.classList.toggle("active") let panel = this.nextElementSibling; if (panel.style.display == "block") { panel.style.display = "none" } else { panel.style.display = "block" } }) } function hide() { for (i = 0; i < acc.length; i++) { acc[i].classList.toggle("active", false); acc[i].nextElementSibling.classList.toggle("show", false); acc[i].nextElementSibling.style.display = "none" } } } 
 .accordion { background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; transition: 0.4s; } .active, .accordion:hover { background-color: #ccc; } .panel { padding: 0 18px; display: none; background-color: white; overflow: hidden; } 
 <body onload="accordion()"> <button class="accordion">Section 1</button> <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> <button class="accordion">Section 2</button> <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> <button class="accordion">Section 3</button> <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> </body> 

I simplified your code a bit using forEach() and ternaries.

The problem was that you were hiding all accordions in your hide() function, but you should not hide the currently opened accordion so you can simply toggle its state.

 document.querySelectorAll('.accordion').forEach((acc, i, all) => { acc.addEventListener('click', () => { hideOthers(acc); acc.classList.toggle('active'); const panelStyle = acc.nextElementSibling.style; panelStyle.display = panelStyle.display === 'block' ? 'none' : 'block'; }) function hideOthers(me) { all.forEach(acc => { if (acc !== me) { acc.classList.remove('active'); acc.nextElementSibling.classList.remove('show'); acc.nextElementSibling.style.display = 'none'; } }); } }); 
 .accordion { background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; transition: 0.4s; } .active, .accordion:hover { background-color: #ccc; } .panel { padding: 0 18px; display: none; background-color: white; overflow: hidden; } 
 <button class="accordion">Section 1</button> <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> <button class="accordion">Section 2</button> <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> <button class="accordion">Section 3</button> <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> 

You will need to keep a track of the currently clicked <div> . Also, you can use the css combinator + as .active+.panel . See code below

 function accordion() { let acc = document.querySelectorAll(".accordion") for (let i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { for (let j = 0; j < acc.length; j++) { if (j !== i) acc[j].classList.remove("active") } this.classList.toggle("active") }) } } 
 .accordion { background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; transition: 0.4s; } .active, .accordion:hover { background-color: #ccc; } .panel { padding: 0 18px; display: none; background-color: white; overflow: hidden; } .active+.panel { display: block; } 
 <body onload="accordion()"> <button class="accordion">Section 1</button> <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> <button class="accordion">Section 2</button> <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> <button class="accordion">Section 3</button> <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> </body> 

You can simplify your code:

  1. css: .active + .panel -> Adjacent sibling so you don't need to use javascript for this part.

  2. in listener remember if current was active, if it was not - "activate" it

 function accordion(){ let acc = document.getElementsByClassName("accordion") let i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { let currentActive = this.classList.contains("active"); hide(); !currentActive && this.classList.add("active"); }) } function hide() { for (i = 0; i < acc.length; i++) { acc[i].classList.remove("active"); } } } 
 .accordion { background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; transition: 0.4s; } .active, .accordion:hover { background-color: #ccc; } .panel { padding: 0 18px; display: none; background-color: white; overflow: hidden; } .active + .panel { display: block; } 
 <body onload="accordion()"> <button class="accordion">Section 1</button> <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> <button class="accordion">Section 2</button> <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> <button class="accordion">Section 3</button> <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> </body> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM