Bootstrap 3 折叠手风琴:全部折叠可以实现,但无法展开所有内容并保持 data-parent。

22

我正在使用 Bootstrap 3 并尝试设置以下手风琴/折叠结构:

  1. 页面加载时:每个手风琴面板在组内完全折叠并按预期工作。

  2. 按钮点击时:每个手风琴面板都会展开,并且单击切换无效(包括 URL 锚点效果)。

  3. 另一个按钮点击时:所有面板返回到 onload 状态;所有的手风琴面板都是正常折叠和可点击的。

我已经完成了第二步,但当我在第三步再次点击该按钮时,它没有任何效果。我还没有在 Chrome Dev Tools 中看到任何控制台错误报告,也没有通过本地 JSHint 运行代码时看到错误。

我希望每次单击按钮时都可以重复这个循环。

我在这里设置了我的代码 http://bootply.com/98140http://jsfiddle.net/A9vCx/

我想知道我做错了什么,欢迎提供建议。谢谢!

我的 HTML 代码:

<button class="collapse-init">Click to disable accordion behavior</button>
<br><br>
<div class="panel-group" id="accordion">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
          Collapsible Group Item #1
        </a>
      </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse">
      <div class="panel-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.
      </div>
    </div>
  </div>
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
          Collapsible Group Item #2
        </a>
      </h4>
    </div>
    <div id="collapseTwo" class="panel-collapse collapse">
      <div class="panel-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.
      </div>
    </div>
  </div>
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">
          Collapsible Group Item #3
        </a>
      </h4>
    </div>
    <div id="collapseThree" class="panel-collapse collapse">
      <div class="panel-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.
      </div>
    </div>
  </div>
</div>

我的JS:

$(function() {

  var $active = true;

  $('.panel-title > a').click(function(e) {
    e.preventDefault();
  });

  $('.collapse-init').on('click', function() {
    if(!$active) {
      $active = true;
      $('.panel-title > a').attr('data-toggle', 'collapse');
      $('.panel-collapse').collapse({'toggle': true, 'parent': '#accordion'});
      $(this).html('Click to disable accordion behavior');
    } else {
      $active = false;
      $('.panel-collapse').collapse({'toggle': true, 'parent': '#accordion'});
      $('.panel-title > a').removeAttr('data-toggle');
      $(this).html('Click to enable accordion behavior');
    }
  });

});
4个回答

50

更新的答案

试图打开多个使用折叠控件设置为手风琴效果(即设置了 data-parent 属性) 的面板,可能会出现很多问题和错误 (请参见 multiple panels open after programmatically opening a panel 这个问题)。

相反,最好的方法是:

  1. 允许每个面板单独切换
  2. 在适当的情况下手动实现手风琴效果。

要允许每个面板单独切换,在 data-toggle="collapse" 元素上,将 data-target 属性设置为 .collapse 面板 ID 选择器(而不是将 data-parent 属性设置为父级控件)。你可以在这个问题中阅读更多相关信息:Modify Twitter Bootstrap collapse plugin to keep accordions open

大致上,每个面板应该像这样:

<div class="panel panel-default">
   <div class="panel-heading">
         <h4 class="panel-title"
             data-toggle="collapse" 
             <b>data-target="#collapseOne"></b>
             Collapsible Group Item #1
         </h4>
    </div>
    <div <b>id="collapseOne" </b>
         class="panel-collapse collapse">
        <div class="panel-body"></div>
    </div>
</div>

若要手动实现手风琴效果,可以创建一个处理程序来处理折叠显示事件,在任何面板显示之前发生。使用此方法确保在显示所选面板之前关闭其他已打开的面板(请参阅此答案以打开多个面板)。您还需要仅在面板处于活动状态时执行代码。为此,请添加以下代码:

$('#accordion').on('show.bs.collapse', function () {
    if (active) $('#accordion .in').collapse('hide');
});
然后使用showhide来切换每个面板的可见性,使用data-toggle来启用和禁用控件。
$('#collapse-init').click(function () {
    if (active) {
        active = false;
        <b>$('.panel-collapse').collapse('show');
        $('.panel-title').attr('data-toggle', '');</b>
        $(this).text('Enable accordion behavior');
    } else {
        active = true;
        <b>$('.panel-collapse').collapse('hide');
        $('.panel-title').attr('data-toggle', 'collapse');</b>
        $(this).text('Disable accordion behavior');
    }
});

jsFiddle中的演示


非常接近了!如果我点击面板1,然后再点击两次“按钮”,然后再点击面板1,接着点击面板2,再次点击“按钮”,那么面板2将会隐藏,并保持关闭状态 :-( - cfx
也有可能是通过加载新文件,然后单击面板1,接着单击面板2,再单击面板3,最后单击“按钮”,导致本应该显示的面板3隐藏了。 - cfx
非常接近了,我再次感谢你 - 我希望我能接受两个答案,因为它们都是不可或缺的! - cfx
我进一步清理了它,因为我们不需要href。我用<p>替换了面板切换锚点,这也意味着我们可以删除preventDefault()部分!http://jsfiddle.net/3NuHh/2/ - cfx
1
我进一步清理了它!如果panel-title中只有一个<p>元素,我们可能不需要它:) jsFiddle - KyleMit
显示剩余6条评论

4

不知为何,$('.panel-collapse').collapse({'toggle': true, 'parent': '#accordion'}); 只能在第一次展开可折叠面板时生效,并且仅用于展开可折叠面板。(我尝试从一个已展开的可折叠面板开始,但它无法折叠。)

可能是由于这些参数只被初始化一次,导致它只能运行一次。

您可以尝试使用 showhide 方法来实现更好的效果。

以下是示例:

$(function() {

  var $active = true;

  $('.panel-title > a').click(function(e) {
    e.preventDefault();
  });

  $('.collapse-init').on('click', function() {
    if(!$active) {
      $active = true;
      $('.panel-title > a').attr('data-toggle', 'collapse');
      $('.panel-collapse').collapse('hide');
      $(this).html('Click to disable accordion behavior');
    } else {
      $active = false;
      $('.panel-collapse').collapse('show');
      $('.panel-title > a').attr('data-toggle','');
      $(this).html('Click to enable accordion behavior');
    }
  });

});

http://bootply.com/98201

更新:

虽然KyleMit似乎比我更擅长这个问题,我对他的回答和理解深感印象深刻。

我不明白正在发生什么,也不知道为什么在某些地方show会被切换。

但是在折腾了一段时间之后……终于想出了以下解决方案:

$(function() {
  var transition = false;
  var $active = true;

  $('.panel-title > a').click(function(e) {
    e.preventDefault();
  });

  $('#accordion').on('show.bs.collapse',function(){
    if($active){
        $('#accordion .in').collapse('hide');
    }
  });

  $('#accordion').on('hidden.bs.collapse',function(){
    if(transition){
        transition = false;
        $('.panel-collapse').collapse('show');
    }
  });

  $('.collapse-init').on('click', function() {
    $('.collapse-init').prop('disabled','true');
    if(!$active) {
      $active = true;
      $('.panel-title > a').attr('data-toggle', 'collapse');
      $('.panel-collapse').collapse('hide');
      $(this).html('Click to disable accordion behavior');
    } else {
      $active = false;
      if($('.panel-collapse.in').length){
        transition = true;
        $('.panel-collapse.in').collapse('hide');       
      }
      else{
        $('.panel-collapse').collapse('show');
      }
      $('.panel-title > a').attr('data-toggle','');
      $(this).html('Click to enable accordion behavior');
    }
    setTimeout(function(){
        $('.collapse-init').prop('disabled','');
    },800);
  });
});

http://bootply.com/98239


3
谢谢@Trevor。使用“show”方法的问题在于,如果您单击两次“按钮”,然后打开面板1,在单击以打开面板2时,面板1仍然保持打开状态,就好像它没有记住分组一样。 - cfx
2
+1 个好答案。关于需要使用 show 的进一步解释:当您调用 collapse 函数(或任何 bootstrap 函数)时,如果传递一个对象,则意味着您启动了折叠。toggle 选项 仅在调用时切换可折叠元素(来自此答案)。 - KyleMit
谢谢@KyleMit!我现在离成功更近了。我添加了一个检查,但是现在我发现的问题是,如果您刷新fiddle,然后显示面板1并单击“按钮”,则面板1将关闭(切换),而不是像其他面板一样显示。http://bootply.com/98224 - cfx
@gordian,请查看我的答案,它应该能够按照需要执行所有操作。 - KyleMit
由于某些原因,e.stopPropagation()对我不起作用,所以我只是使用了return false; - Ivan

3

为了在想要使用“隐藏”和“显示”功能(如.collapse('hide'))时保持手风琴的特性不变,您必须在调用“隐藏”或“显示”之前使用toggle: false在对象中设置父级属性初始化可折叠的面板。

// initialize collapsible panels
$('#accordion .collapse').collapse({
  toggle: false,
  parent: '#accordion'
});

// show panel one (will collapse others in accordion)
$( '#collapseOne' ).collapse( 'show' );

// show panel two (will collapse others in accordion)
$( '#collapseTwo' ).collapse( 'show' );

// hide panel two (will not collapse/expand others in accordion)
$( '#collapseTwo' ).collapse( 'hide' );

-1

最好且经过测试的解决方案是放置以下小片段,它将折叠已打开的手风琴选项卡。在我的情况下,第六个选项卡是打开的,因此我在页面加载时将其折叠。

 $(document).ready(){
      $('#collapseSix').collapse("hide");
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接