Javascript Accordian-折叠除活动状态以外的所有打开的实例

时间:2019-02-11 23:35:46

标签: javascript jquery html collapse

我正在使用一个简单的JavaScript手风琴手来打开/关闭列表项,如下所示。 是否可以确保在打开一个新列表项时关闭所有打开的列表项(而不是当前的方式,即在手动关闭每个列表项之前将其保持打开状态)?

CODEPEN此处:

https://codepen.io/anon/pen/zejJpJ

JS

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

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

HTML

<ul class="track-listing">
  <li>
    <button class="accordion">TITLE</button>
    <div class="panel">
    <p>Panel content</p>
    </div>
  </li>
  <li>
    <button class="accordion">TITLE</button>
    <div class="panel">
    <p>Panel content</p>
    </div>
  </li>
  <li>
    <button class="accordion">TITLE</button>
    <div class="panel">
    <p>Panel content</p>
    </div>
  </li>
</ul>

3 个答案:

答案 0 :(得分:3)

是的,可以通过在打开新的手风琴之前关闭所有其他手风琴来实现:

for (var j = 0; j < acc.length; j++) {
  var button = acc[j];

  if (button === this) continue;

  button.classList.remove("active");
  var panel = button.nextElementSibling;
  panel.style.maxHeight = null;
}

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

for (var i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    // Close all other accordions
    for (var j = 0; j < acc.length; j++) {
      var button = acc[j];
      
      if (button === this) continue;
      
      button.classList.remove("active");
      var panel = button.nextElementSibling;
      panel.style.maxHeight = null;
    }

    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
  });
}
.accordion {
  background-color: #1e1e1e;
  color: #c0b9b4;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 1em;
  transition: 0.4s;
  margin: 0 0 2px 0;
}

ul.track-listing {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

.active,
.accordion:hover {
  background-color: #c0b9b4;
  color: #1e1e1e;
}

.accordion:after {
  content: 'LYRICS \002B ';
  color: #777;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "\2212";
}

.panel {
  padding: 0 18px;
  background-color: #1e1e1e;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
  color: #c0b9b4;
}
<ul class="track-listing">
  <li>
    <button class="accordion">TITLE</button>
    <div class="panel">
      <p>Panel content</p>
    </div>
  </li>
  <li>
    <button class="accordion">TITLE</button>
    <div class="panel">
      <p>Panel content</p>
    </div>
  </li>
  <li>
    <button class="accordion">TITLE</button>
    <div class="panel">
      <p>Panel content</p>
    </div>
  </li>
</ul>

答案 1 :(得分:2)

是的,您可以再次遍历acc数组并关闭索引与闭包不相同的手风琴。

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

for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function () {
        toggleAccordion(this);
        if (this.classList.contains("active")) {
          for (var j = 0; j < acc.length; j++) {
            if (i != j) {
              acc[j].nextElementSibling.style.maxHeight = null;
            }
          }
        }
    });
}

function toggleAccordion(button) {
  button.classList.toggle("active");
  var panel = button.nextElementSibling;
  if (panel.style.maxHeight) {
    panel.style.maxHeight = null;
  } else {
    panel.style.maxHeight = panel.scrollHeight + "px";
  }
}

答案 2 :(得分:2)

您可以通过具有可以被特定关闭状态覆盖的切换功能来做到这一点。这样,您就可以在切换之前关闭除单击的对象之外的所有对象。这是forked pen,下面是代码。

var acc = document.getElementsByClassName("accordion")

const toggleAccordian = (acc, open = !acc.classList.contains('active')) => {  
  acc.classList.toggle('active', open)
  const panel = acc.nextElementSibling
  panel.style.maxHeight = open ? panel.scrollHeight + "px" : null  
}

const elems = Array.from(acc)
elems.forEach(a => {
  a.addEventListener('click', () => {
    elems
      .filter(e => e !== a)
      .forEach(e => toggleAccordian(e, false))
    toggleAccordian(a)
  })
})