Javascript 手风琴 - 折叠除活动之外的所有打开实例

Javascript accordian - collapse all open instances except active

我正在使用简单的 javascript 手风琴来 open/close 列出项目,如下所示。 是否可以确保在打开新列表项时关闭所有打开的列表项(而不是当前让每个列表项都打开直到手动关闭的方式)?

代码在这里:

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>

是的,您可以再次遍历 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";
  }
}

是的,您可以在打开新手风琴之前关闭所有其他手风琴:

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 [=12=]2B ';
  color: #777;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "12";
}

.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>

您可以通过一个可以用特定的关闭状态覆盖的切换函数来实现。这样,您只需在切换之前关闭所有内容,除了单击的那个。这是 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)
  })
})