Colapso do 'bootstrap' do Twitter: mudar a apresentação do botão de comutação

Estou a usar o Twitter Bootstrap para criar secções desmontáveis de texto. As secções são expandidas quando um botão + é pressionado. O meu código html é o seguinte:

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

existe uma forma de mudar o botão para mostrar {[[2]} em vez de + depois de a secção ser expandida (e mudar para + quando for colapsada novamente)?

informações adicionais: esperava que houvesse uma solução simples para o meu problema baseada no twitter-bootstrap/css/html. Todas as respostas até agora faça uso de JavaScript ou PHP. Por causa disso, eu quero adicionar mais informações sobre o meu ambiente de desenvolvimento: eu quero usar esta solução dentro de um site baseado em SilverStripe (versão 3.0.5) que tem algumas implicações para o uso de PHP, bem como JavaScript.

Author: Markus M., 2013-04-26

9 answers

Experimenta isto. http://jsfiddle.net/fVpkm/

Html:-

<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=='+' ?  '-' : '+';
    });
});

Actualizar com Css puro, pseudo-Elementos

Http://jsfiddle.net/r4Bdz/

Navegadores Suportados

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

Actualizar 2 com Javascript puro

Http://jsfiddle.net/WteTy/

function handleClick()
{
    this.value = (this.value == '+' ? '-' : '+');
}
document.getElementById('collapsible').onclick=handleClick;
 63
Author: PSL, 2013-04-26 02:26:31

Aqui está outra solução CSS apenas que funciona com qualquer disposição HTML .

Funciona com qualquer elemento que precise de mudar. Seja qual for a sua disposição de comutação, basta colocá-la dentro de alguns elementos com as classes if-collapsed e if-not-collapsed dentro do elemento de comutação.

O único senão é ter a certeza que coloca o estado inicial desejado da comutação. Se estiver inicialmente fechada, então coloque uma classe collapsed na comutação.

Também requer a Selector, por isso não funciona na IE8.

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

Menos versão:

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

Versão CSS:

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

Violino JS

 38
Author: Jens, 2017-09-06 01:27:43

Todas as outras soluções publicadas aqui fazem com que a comutação fique fora de sincronia se for clicado duas vezes. A seguinte solução usa os Eventos fornecidos pela estrutura de Bootstrap , e a comutação corresponde sempre ao estado do elemento desmontável:

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('+')
})
Isso deve funcionar para a maioria dos casos. No entanto, também encontrei um problema adicional ao tentar aninhar um elemento desmontável e a sua comutação. troca dentro de outro elemento desmontável. Com o código acima, quando eu carregar na opção aninhada para esconder o elemento desmontável aninhado, a opção para o elemento pai também muda. Pode ser um bug no Bootstrap. Encontrei uma solução que parece funcionar: adicionei uma classe "colapsada" aos interruptores de comutação( Bootstrap adiciona isto quando o elemento desmontável está escondido, mas eles não começam com ele), e adicionou isso ao selector de jQuery para o hide função:

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')
})
 5
Author: linesarefuzzy, 2013-12-04 17:58:43

Adicione algum código jquery, você precisa jquery para fazer isso:

<script>
        $(".btn[data-toggle='collapse']").click(function() {
            if ($(this).text() == '+') {
                $(this).text('-');
            } else {
                $(this).text('+');
            }
        });
        </script>
 3
Author: AzDesign, 2013-04-25 21:14:26

Eu acho que você poderia olhar dentro do seu código baixado onde exatamente há um sinal {[[2]} (mas isso pode não ser muito fácil).

O que eu faria? Eu encontraria a classe / id dos elementos DOM que contêm o sinal + (suponha que seja ".collapsible", e com Javascript (na verdade jQuery):
<script>
     $(document).ready(function() {
         var content=$(".collapsible").html().replace("+", "-");
         $(".collapsible").html(content));
     });
</script>

Editar Ok... Desculpa não ter visto o código de presilha... mas acho que funciona com algo como slideToggle, ou slideDown and slideUp... Imagine que é um slideToggle para os elementos da classe .collapsible, que revelam o conteúdo de alguns elementos .info. Então:

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

Isto parece ser a coisa oposta a fazer, mas uma vez que a animação actual é executada em paralelo, você irá verificar o css antes da animação, e é por isso que você precisa de verificar se é visível (o que significa que será escondido assim que a animação estiver completa) e, em seguida, definir o + ou-correspondente.

 1
Author: Nico, 2013-04-28 08:41:28
A minha solução JS seguinte é melhor do que as outras abordagens aqui porque garante que vai sempre dizer "aberto" quando o alvo está fechado, e vice-versa.

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

Exemplos:

$('[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>

Violino JS

Outros benefícios desta abordagem:
  • o código é seco e reutilizável
  • Cada botão de colapso fica separado.
  • só precisas para colocar uma alteração no HTML: adicionar o atributo data-toggle-secondary
 1
Author: Harvey, 2017-06-23 13:59:15

Eu gostei da solução apenas de CSS do PSL , mas no meu caso eu precisava de incluir algum HTML no botão, e a propriedade de Css de conteúdo está a mostrar o HTML raw com marcas neste caso.

Caso isso possa ajudar outra pessoa, pedi-lhe o violino para cobrir o meu caso de uso. 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;
}
 0
Author: Bruno A., 2017-05-23 11:47:16

Mais fácil com codificação em linha

<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
Author: Swapna Jerin, 2015-11-06 09:10:09
([3]}Alguns podem ter problemas com a mudança do Bootstrap js (e talvez validamente), mas aqui está uma abordagem de duas linhas para alcançar isso.

In bootstrap.js, procura o colapso.prototipo.mostrar a função e modificar isto.$trigger call para adicionar a mudança de html do seguinte modo:

this.$trigger
  .removeClass('collapsed')
  .attr('aria-expanded', true)
  .html('Collapse')

Igualmente no colapso.prototipo.esconder a função Mudar para

this.$trigger
  .addClass('collapsed')
  .attr('aria-expanded', false)
  .html('Expand')

Isto irá alternar o texto entre "colapsar" quando tudo for expandido e" expandir " quando tudo for recolhida.

Duas linhas. Terminar.

Edite: a longo prazo isto não vai funcionar. arranque.o js faz parte de um pacote Nuget, por isso acho que não estava a promover a minha mudança para o servidor. Como mencionado anteriormente, não é uma boa prática para editar bootstrap.js, então implementei a solução do PSL que funcionou muito bem. No entanto, a minha solução funcionará localmente se precisar de algo rápido apenas para experimentá-lo.

 0
Author: scottndecker, 2016-05-11 13:03:07