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

Posted

技术标签:

【中文标题】Javascript手风琴 - 折叠除活动之外的所有打开实例【英文标题】:Javascript accordian - collapse all open instances except active 【发布时间】:2019-07-05 13:07:50 【问题描述】:

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

在这里编码:

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>

【问题讨论】:

【参考方案1】:

是的,您可以再次遍历 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】:

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

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>

【讨论】:

谢谢 - 这很好用,但它不允许打开列表项在打开后关闭。这有意义吗?打开第一个项目,然后尝试关闭它。 对不起,我的错误,更新了示例(可能不是最干净的解决方案,但它有效)【参考方案3】:

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

【讨论】:

以上是关于Javascript手风琴 - 折叠除活动之外的所有打开实例的主要内容,如果未能解决你的问题,请参考以下文章

javascript 默认情况下折叠的手风琴

Jquery 手风琴没有删除类,也没有将其展开文本交换为折叠

当另一个手风琴面板打开时折叠手风琴面板

如何使手风琴标题在页面加载时全部折叠?

在可扩展列表视图android中折叠除选定组之外的所有组

带有 Bootstrap 折叠插件的 Javascript 切换