【问题标题】:Only open one accordion tab at one time一次只能打开一个手风琴标签
【发布时间】:2016-10-11 05:44:53
【问题描述】:

我有一架手风琴,效果非常好,它在网站上看起来不错,并且可以正常工作。不过,我正在尝试为其添加更多 JavaScript 功能,使其看起来更专业。

目前,手风琴允许您一次打开多个面板,即如果我打开一个选项卡,然后打开另一个选项卡,两个选项卡将同时打开。关闭这些面板的唯一方法是重新单击标题。

我想要的是一些 JavaScript 代码,它可以防止同时打开多个选项卡,所以如果我点击一个新面板,它应该首先关闭现有的打开面板。这是我的手风琴 HTML 代码:

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

这是我在一个单独的 JavaScript 文件中的 JavaScript 代码,目前允许同时打开多个选项卡

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");
    }
}

不确定是否需要所有 CSS,但这里是用于显示面板的 CSS

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

希望有人可以提供帮助!提前致谢!

【问题讨论】:

标签: javascript html accordion


【解决方案1】:

要实现这一点,您需要在每次点击时将手风琴的状态重置回其原始状态,然后再为点击的元素设置所需的类。为此,您可以提取功能以将类名设置为它们自己的函数并根据需要调用它。试试这个:

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

【讨论】:

  • 有效!!太感谢了!对此,我真的非常感激。我还想添加一个功能,但是,我不确定它是否可能......当您单击手风琴标题时,我希望页面向下滚动到打开的手风琴顶部,以便用户可以看到所有内容。这是可以做到的吗?再次 - 非常感谢上面的回答!
  • 很高兴为您提供帮助。您可以通过将document.body.scrollTop = this.offsetTop; 添加到点击处理程序来做到这一点:jsfiddle.net/5h5evjpw/1
  • 嘿!感谢您的快速回复!我试过那个代码,它做了一些奇怪的事情,当我点击手风琴时,它把打开的手风琴放在我的页面底部,所以我可以看到标题,但是面板中的文本离开了我的屏幕,任何关于如何解决这个问题的想法?
  • 不看例子就很难诊断。最好为此提出一个新问题 - 但如果可以的话,请记住包含所有代码和一个工作示例
  • 嘿!你的解决方案奏效了!我刚刚在代码末尾添加了一个“+750”,它将页面定位到正确的页面 - 所以谢谢!最后一个问题 - 目前它的跳跃而不是平滑滚动,知道如何减慢屏幕的移动速度,让它有更平滑的感觉吗?谢谢!
【解决方案2】:

在打开所选标签之前关闭所有打开的标签。这将防止同时打开多个标签。

// Get all Accordion and Panel
let accHeading = document.querySelectorAll(".accordion");
let accPanel = document.querySelectorAll(".accordion-panel");

for (let i = 0; i < accHeading.length; i++) {
    // Execute whenever an accordion is clicked 
    accHeading[i].onclick = function() {
        if (this.nextElementSibling.style.maxHeight) {
           hidePanels();     // Hide All open Panels 
        } else {
           showPanel(this);  // Show the panel
        } 
    };
}

// Function to Show a Panel
function showPanel(elem) {
  hidePanels();
  elem.classList.add("active");
  elem.nextElementSibling.style.maxHeight = elem.nextElementSibling.scrollHeight + "px";
}

// Function to Hide all shown Panels
function hidePanels() {
  for (let i = 0; i < accPanel.length; i++) {
      accPanel[i].style.maxHeight = null;
      accHeading[i].classList.remove("active");
  }
}
* {box-sizing: border-box;}

/* Style the Headings that are used to open and close the accordion panel */
.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  margin: 0;
  font-weight: 300;
}

/* Change color of the heading and icon (on hover and click) */
.active, .accordion:hover, .accordion:hover::after {
  background-color: #007eff;
  color: white;
}

/* Add "plus" sign (+) after Accordion */
.accordion::after {
  content: '\002B';
  color: #777;
  font-weight: bold;
  float: right;
}

/* Add "minus" sign (-) after Accordion (when accordion is active) */
.active::after {
  content: "\2212";
  color: white;
}

/* Style the accordion panel */
.accordion-panel {
  padding: 0 18px;
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.2s ease-out;
}
<div style="border: 1px solid lightgray;">
  <h2 class="accordion">Section 1</h2>
  <div class="accordion-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>

  <h2 class="accordion">Section 2</h2>
  <div class="accordion-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>

  <h2 class="accordion">Section 3</h2>
  <div class="accordion-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>

  <h2 class="accordion">Section 4</h2>
  <div class="accordion-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>
</div>

【讨论】:

    【解决方案3】:

    选择一项时,只需事先将其全部隐藏即可。

    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】:
      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;
          }
      }
      

      变量 last 将跟踪最后一个活动的手风琴,因此您无需再次迭代每个手风琴和面板。

      【讨论】:

        【解决方案5】:

        你必须用手风琴盖住面板,这样你就可以轻松做到这一点。

        参考这个

        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

        【讨论】:

        • OP 没有使用jQuery
        猜你喜欢
        • 2013-03-22
        • 2021-12-03
        • 1970-01-01
        • 2022-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-11
        • 2022-12-18
        相关资源
        最近更新 更多