Only open one accordion tab at one time

2019-02-10 15:24发布

I have an accordion that works really well, it looks good on the site and works as it should. However, I'm trying to add some more JavaScript functionality to it, to make it more it look more professional.

Currently, the accordion allows you to have multiple panels open at one time i.e. if I open one tab, and then open another tab, both tabs will be open at the same time. And the only way to close these panels, is to re-click on the header.

What I would like is some JavaScript code that prevents multiple tabs from being open at one time, so if I click on a new panel, it should close the existing open panel first. Here is my HTML code for the accordion:

<div class="accordion"><b>Heading 1</b></div>
<div class="panel">
    <p class="text-light">Text 1</p>
</div>
<div class="accordion"><b>Heading 2</b></div>
<div class="panel">
    <p class="text-light">Text 2</p>
</div>

Here is my JavaScript code in a separate JavaScript file which currently allows multiple tabs to be open at one time

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

for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
    }
}

Not sure if you need all the CSS, but heres the CSS for showing the panel

div.panel.show {
    display: block !important;
}

Hopefully someone can help! Thanks in advance!

4条回答
爷、活的狠高调
2楼-- · 2019-02-10 15:46

you have to cover the panel with accordion, so you can easily do that.

refer this

html
<div class="accordion"><b>Heading 1</b>
    <div class="panel">
        <p class="text-light">Text 1</p>
    </div>
    </div>
<div class="accordion"><b>Heading 2</b>
    <div class="panel">
        <p class="text-light">Text 2</p>
    </div>
    </div>

jquery:
$('.accordion').click(function() {
$(this).find('.panel').show();
$(this).siblings().find('.panel').hide();

});

Working example

查看更多
你好瞎i
3楼-- · 2019-02-10 15:47

When selecting one item, you just need to hide all of them beforehand.

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

for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
        hideAll();

        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
    }
}

function hideAll() {
    for (i = 0; i < acc.length; i++) {
        acc[i].classList.toggle("active", false);
        acc[i].nextElementSibling.classList.toggle("show", false);
    }
}
查看更多
地球回转人心会变
4楼-- · 2019-02-10 15:49
var acc = document.getElementsByClassName("accordion");
var i;
var last;
for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
        if(last){
            last.classList.toggle("active",false);
            last.nextElementSibling.classList.toggle("show",false);
        }
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
        last=this;
    }
}

variable last will track the last active accordion, so you don't need to iterate every accordion and panel again.

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-02-10 16:02

To achieve this you need to reset the state of the accordion back to its original state on each click, before you set the required classes on the clicked elements. To do that you can extract functionality to set the class names in to their own function and call it as required. Try this:

var acc = document.getElementsByClassName("accordion");
var panel = document.getElementsByClassName('panel');

for (var i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
        var setClasses = !this.classList.contains('active');
        setClass(acc, 'active', 'remove');
        setClass(panel, 'show', 'remove');

        if (setClasses) {
            this.classList.toggle("active");
            this.nextElementSibling.classList.toggle("show");
        }
    }
}

function setClass(els, className, fnName) {
    for (var i = 0; i < els.length; i++) {
        els[i].classList[fnName](className);
    }
}

Working example

查看更多
登录 后发表回答