Twitter Bootstrap 折叠:更改切换按钮的显示方式

77

我正在使用Twitter Bootstrap创建可折叠的文本区域。当按下“+”按钮时,这些区域会展开。我的html代码如下:

<div class="row-fluid summary">
    <div class="span11">
        <h2>MyHeading</h2>  
    </div>
    <div class="span1">
        <button type="button" class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
    </div>
</div>
<div class="row-fluid summary">
    <div id="intro" class="collapse"> 
        Here comes the text...
    </div>
</div>
有没有办法在部分内容展开后(并在折叠时改回 +),将按钮更改为显示“-”而不是“+”?
附加信息:我希望有一个简单的基于Twitter Bootstrap / CSS / HTML的解决方案来解决我的问题。到目前为止,所有的回复都使用JavaScript或PHP。因此,我想添加一些关于我的开发环境的信息:我想在基于SilverStripe(版本3.0.5)的网站中使用此解决方案,这对PHP和JavaScript的使用有一定的影响。
11个回答

99

试试这个。 http://jsfiddle.net/fVpkm/

<div class="row-fluid summary">
    <div class="span11">
        <h2>MyHeading</h2>  
    </div>
    <div class="span1">
        <button class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
    </div>
</div>
<div class="row-fluid summary">
    <div id="intro" class="collapse"> 
        Here comes the text...
    </div>
</div>

JS:-

$('button').click(function(){ //you can give id or class name here for $('button')
    $(this).text(function(i,old){
        return old=='+' ?  '-' : '+';
    });
});

更新使用纯CSS,伪元素

http://jsfiddle.net/r4Bdz/

支持的浏览器

button.btn.collapsed:before
{
    content:'+' ;
    display:block;
    width:15px;
}
button.btn:before
{
    content:'-' ;
    display:block;
    width:15px;
}

更新2使用纯JavaScript

http://jsfiddle.net/WteTy/

function handleClick()
{
    this.value = (this.value == '+' ? '-' : '+');
}
document.getElementById('collapsible').onclick=handleClick;

2
嗨,我已经用纯CSS的解决方案更新了我的答案。可能这对你有用。 - PSL
1
没有通过jQuery解决方案或基于CSS的解决方案成功,但是纯JavaScript终于解决了问题。我想jQuery和CSS遇到了我使用的SilverStripe-Twitter-Bootstrap主题创建的副作用。非常感谢你们的努力,我真的很感激!除了现在有了解决我的问题的方法,我还从你们的建议中学到了很多。 - Markus M.
很高兴能够帮助您解决问题.. :) - PSL
1
找到了如何使用基于jQuery的解决方案,只需要找到正确的位置包含脚本。更加优雅,因为可以立即应用于多个部分。 - Markus M.
4
请注意,如果您反复快速点击按钮,此功能将失去同步。那是因为折叠操作还没有完成执行。可以通过在折叠完成前禁用其他点击来防止这种情况发生。 - Voodoo
显示剩余2条评论

87

这是另一个CSS only的解决方案,适用于任何HTML布局

它适用于您需要切换的任何元素。无论您的切换布局是什么,您只需将其放置在带有if-collapsedif-not-collapsed类的几个元素内,这些元素位于切换元素内部。

唯一的注意点是确保您放置了所需的初始切换状态。如果初始情况下关闭,则在切换上放置collapsed类。

它还需要使用:not选择器,因此在IE8上无法正常工作。

HTML示例:

<a class="btn btn-primary collapsed" data-toggle="collapse" href="#collapseExample">
  <!--You can put any valid html inside these!-->
  <span class="if-collapsed">Open</span>
  <span class="if-not-collapsed">Close</span>
</a>
<div class="collapse" id="collapseExample">
  <div class="well">
    ...
  </div>
</div>
Less 版本:
[data-toggle="collapse"] {
    &.collapsed .if-not-collapsed {
         display: none;
    }
    &:not(.collapsed) .if-collapsed {
         display: none;
    }
}

CSS版本:

[data-toggle="collapse"].collapsed .if-not-collapsed {
  display: none;
}
[data-toggle="collapse"]:not(.collapsed) .if-collapsed {
  display: none;
}

JS Fiddle


1
这是一个很棒的答案。希望我能多次点赞。 - Chris
1
我喜欢这个答案,但似乎Bootstrap(2.3.1)在单击锚元素时添加.collapse存在一个错误。这意味着如果实际目标已经显示,该类可能会变得不同步。 - harvzor
1
@Harvey 我只在Bootstrap 3上测试过,我已经很久没有使用Bootstrap 2了。 - Jens
9
这是一个非常优雅的解决方案。请注意,要使其正常工作: 如果某个部分是折叠的,请确保切换元素具有“collapsed”类。 如果某个部分因为有“collapse in”类而被展开,请确保切换元素没有“collapsed”类。示例:http://jsfiddle.net/ahx7r627/。 - evophage
1
简单而优雅,适用于v4和2022。赞! - petrosmm
显示剩余4条评论

6

添加一些jQuery代码,你需要使用jQuery来完成这个操作:

<script>
        $(".btn[data-toggle='collapse']").click(function() {
            if ($(this).text() == '+') {
                $(this).text('-');
            } else {
                $(this).text('+');
            }
        });
        </script>

谢谢您的回答。这看起来是正确的解决方案。不过我还没有在我的SilverStripe实例中成功运行它。 - Markus M.
希望我能给这个更多的赞。迄今为止,这是将此功能添加到现有代码中最简单、最干净的方法 - 谢谢! - Hondaman900

5
所有其他在此发布的解决方案,如果双击,则会导致切换不同步。以下解决方案使用Bootstrap框架提供的事件,并且切换始终与可折叠元素的状态匹配:
HTML:
<div class="row-fluid summary">
    <div class="span11">
        <h2>MyHeading</h2>  
    </div>
    <div class="span1">
        <button id="intro-switch" class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
    </div>
</div>
<div class="row-fluid summary">
    <div id="intro" class="collapse"> 
        Here comes the text...
    </div>
</div>

JS:

$('#intro').on('show', function() {
  $('#intro-switch').html('-')
})
$('#intro').on('hide', function() {
  $('#intro-switch').html('+')
})

那应该适用于大多数情况。
然而,当我试图将一个可折叠元素及其切换开关嵌套在另一个可折叠元素中时,我遇到了一个额外的问题。使用上述代码时,当我单击嵌套的切换以隐藏嵌套的可折叠元素时,父元素的切换也会更改。这可能是 Bootstrap 中的一个错误。我找到了一个看起来有效的解决方案:我给切换开关添加了一个“collapsed”类(Bootstrap 在可折叠元素被隐藏时添加了这个类,但它们并没有从一开始就有),然后将其添加到 hide 函数的 jQuery 选择器中。

http://jsfiddle.net/fVpkm/87/

HTML:

<div class="row-fluid summary">
    <div class="span11">
        <h2>MyHeading</h2>  
    </div>
    <div class="span1">
        <button id="intro-switch" class="btn btn-success collapsed" data-toggle="collapse" data-target="#intro">+</button>
    </div>
</div>
<div class="row-fluid summary">
    <div id="intro" class="collapse"> 
        Here comes the text...<br>
        <a id="details-switch" class="collapsed" data-toggle="collapse" href="#details">Show details</a>
        <div id="details" class="collapse">
            More details...
        </div>
    </div>
</div>

JS:

$('#intro').on('show', function() {
    $('#intro-switch').html('-')
})
$('#intro').on('hide', function() {
    $('#intro-switch.collapsed').html('+')
})

$('#details').on('show', function() {
    $('#details-switch').html('Hide details')
})
$('#details').on('hide', function() {
    $('#details-switch.collapsed').html('Show details')
})

可能嵌套问题是事件冒泡/传播的问题吗?应该能够停止它。 - JoeBrockhaus
3
对于任何想尝试此操作的人,请注意,在最新版本的bootstrap中,事件名称为'show.bs.collapse'和'hide.bs.collapse'。 - Avi

4

我喜欢PSL的 CSS-only solution,但在我的情况下,我需要在按钮中包含一些HTML,并且内容CSS属性显示了带有标签的原始HTML。

如果这可以帮助其他人,我已经分叉了他的fiddle以覆盖我的用例:http://jsfiddle.net/brunoalla/99j11h40/2/

HTML:

<div class="row-fluid summary">
    <div class="span11">
        <h2>MyHeading</h2>  
    </div>
    <div class="span1">
        <button class="btn btn-success collapsed" data-toggle="collapse" data-target="#intro">
            <span class="show-ctrl">
                <i class="fa fa-chevron-down"></i> Expand
            </span>
            <span class="hide-ctrl">
                <i class="fa fa-chevron-up"></i> Collapse
            </span>            
        </button>
    </div>
</div>
<div class="row-fluid summary">
    <div id="intro" class="collapse"> 
        Here comes the text...
    </div>
</div>

CSS:

button.btn .show-ctrl{
    display: none;
}
button.btn .hide-ctrl{
    display: block;
}
button.btn.collapsed .show-ctrl{
    display: block;
}
button.btn.collapsed .hide-ctrl{
    display: none;
}

3

以下是我的JS解决方案,与其他方法相比更好,因为它确保当目标关闭时,它始终会显示“open”,反之亦然。

HTML:

<a href="#collapseExample" class="btn btn-primary" data-toggle="collapse" data-toggle-secondary="Close">
    Open
</a>
<div class="collapse" id="collapseExample">
  <div class="well">
    ...
  </div>
</div>

JS:

$('[data-toggle-secondary]').each(function() {
    var $toggle = $(this);
    var originalText = $toggle.text();
    var secondaryText = $toggle.data('toggle-secondary');
    var $target = $($toggle.attr('href'));

    $target.on('show.bs.collapse hide.bs.collapse', function() {
        if ($toggle.text() == originalText) {
            $toggle.text(secondaryText);
        } else {
            $toggle.text(originalText);
        }
    });
});

例子:

$('[data-toggle-secondary]').each(function() {
    var $toggle = $(this);
    var originalText = $toggle.text();
    var secondaryText = $toggle.data('toggle-secondary');
    var $target = $($toggle.attr('href'));

    $target.on('show.bs.collapse hide.bs.collapse', function() {
        if ($toggle.text() == originalText) {
            $toggle.text(secondaryText);
        } else {
            $toggle.text(originalText);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"/>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>

<a href="#collapseExample" class="btn btn-primary" data-toggle="collapse" data-toggle-secondary="Close">
    Open
</a>
<div class="collapse" id="collapseExample">
  <div class="well">
    ...
  </div>
</div>

JS Fiddle

这种方法的其他好处:

  • 代码DRY且可重用
  • 每个折叠按钮都是独立的
  • 您只需要在HTML中添加data-toggle-secondary属性即可进行一次更改

1
我猜你可以查看已下载的代码,找到确切的位置有一个+符号(但这可能不太容易)。
我会怎么做呢? 我会找到包含+符号的DOM元素的类/ID(假设是".collapsible"),然后使用JavaScript(实际上是jQuery):
<script>
     $(document).ready(function() {
         var content=$(".collapsible").html().replace("+", "-");
         $(".collapsible").html(content));
     });
</script>

编辑 好的...抱歉我还没有看过bootstrap代码...但我猜它可以用类似slideToggleslideDown和slideUp之类的东西来工作...想象一下,它是针对类.collapsible元素的slideToggle,它会显示一些.info元素的内容。那么:

         $(".collapsible").click(function() { 
             var content=$(".collapsible").html();
             if $(this).next().css("display") === "none") { 
                 $(".collapsible").html(content.replace("+", "-"));
             }
             else $(".collapsible").html(content.replace("-", "+"));
         });

这似乎是相反的做法,但由于实际动画是并行运行的,您将在动画之前检查CSS,这就是为什么需要检查它是否可见(这意味着一旦动画完成,它将被隐藏),然后设置相应的+或-。

感谢您的回复。+ 是我 button 定义的一部分(请查看上面的代码)。如果我正确理解了您的代码,那么它将在页面完全加载后替换所有 + 的实例为 -。然而,我需要的是在单击 + 按钮后将 + 替换为 - - Markus M.
嘿,请再检查一下我的答案。我已经编辑过了,这样你就可以更清楚地阅读它了。 - Nico
谢谢你的努力。我已经接受了第一个提出类似基于jQuery的解决方案的答案。 - Markus M.

0

使用内联编码更容易

<button type="button" ng-click="showmore = (showmore !=null && showmore) ? false : true;" class="btn float-right" data-toggle="collapse" data-target="#moreoptions">
            <span class="glyphicon" ng-class="showmore ? 'glyphicon-collapse-up': 'glyphicon-collapse-down'"></span>
            {{ showmore !=null && showmore ? "Hide More Options" : "Show More Options" }}
        </button>


<div id="moreoptions" class="collapse">Your Panel</div>

0
一些人可能对更改Bootstrap js有异议(也许是合理的),但这里提供了一个两行代码的方法来实现这个目标。
在bootstrap.js中,查找Collapse.prototype.show函数,并修改this.$trigger调用以添加以下HTML更改:
this.$trigger
  .removeClass('collapsed')
  .attr('aria-expanded', true)
  .html('Collapse')

同样地,在 Collapse.prototype.hide 函数中将其更改为:
this.$trigger
  .addClass('collapsed')
  .attr('aria-expanded', false)
  .html('Expand')

这将在所有内容展开时将文本切换为“折叠”,而在所有内容折叠时将文本切换为“展开”。

两行。完成。

编辑:从长远来看,这不起作用。bootstrap.js是Nuget包的一部分,因此我认为它没有将我的更改传播到服务器。正如先前提到的,编辑bootstrap.js并不是最佳实践,因此我实施了PSL的解决方案,效果很好。尽管如此,如果您需要快速尝试某些内容,我的解决方案在本地将起作用。


0

应用并在Bootstrap 5.0.1中运行。 使用简单的jQuery

jQuery('button').on( 'click', function(){
    if(jQuery(this).hasClass('collapsed')){
        jQuery(this).html('+');
    } else {
        jQuery(this).html('-');
    }
});

您还可以使用字体图标或HTML代替+/-符号。


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