Adicionando ícone aberto / fechado aos recolhíveis do Twitter Bootstrap (acordeões)

86

Eu configurei esta versão simples do acordeão Bootstrap :

Acordeão simples: http://jsfiddle.net/darrenc/cngPS/

Atualmente o ícone apenas aponta para baixo , mas alguém sabe qual JS seria necessário para ser implementado para alterar a classe do ícone para:

<i class="icon-chevron-up"></i>

... para que aponte para cima quando expandido e alterne de volta para baixo quando colapsado, e assim quarto?

Darren
fonte

Respostas:

93

Aqui está a resposta para quem está procurando uma solução no Bootstrap 3 (como eu).

A parte HTML:

<div class="btn-group">
  <button type="button" class="btn btn-danger">Action</button>
  <button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#demo">
    <span class="glyphicon glyphicon-minus"></span>
  </button>
</div>
<div id="demo" class="collapse in">Some dummy text in here.</div>

A parte js:

$('.collapse').on('shown.bs.collapse', function(){
$(this).parent().find(".glyphicon-plus").removeClass("glyphicon-plus").addClass("glyphicon-minus");
}).on('hidden.bs.collapse', function(){
$(this).parent().find(".glyphicon-minus").removeClass("glyphicon-minus").addClass("glyphicon-plus");
});

Exemplo de acordeão:

Exemplo de acordeão Bootply

Andrei Veve
fonte
6
exatamente o que é necessário para o bootstrap 3.x. se estiver usando 2.x remova .bs.collapse. Eu também mudei shown and hidden to show and hidepara que a animação aconteça antes de o acordeão abrir.
user1881482
2
esta deve ser a resposta certa porque funciona na versão 4 também
Andres Felipe
Que tal acordeões aninhados? os elementos filhos não têm divisas, mas ainda estou conseguindo ligar o pai.
esotérico
48

Aqui está minha abordagem para o Bootstrap 2.x. É apenas alguns css. Não é necessário JavaScript:

    .accordion-caret .accordion-toggle:hover {
        text-decoration: none;
    }
    .accordion-caret .accordion-toggle:hover span,
    .accordion-caret .accordion-toggle:hover strong {
        text-decoration: underline;
    }
    .accordion-caret .accordion-toggle:before {
        font-size: 25px;
        vertical-align: -3px;
    }
    .accordion-caret .accordion-toggle:not(.collapsed):before {
        content: "▾";
        margin-right: 0px;
    }
    .accordion-caret .accordion-toggle.collapsed:before {
        content: "▸";
        margin-right: 0px;
    }

Basta adicionar o circunflexo acordeão da classe ao div do grupo acordeão, assim:

<div class="accordion-group accordion-caret">
    <div class="accordion-heading">
        <a class="accordion-toggle" data-toggle="collapse" href="#collapseOne">
            <strong>Header</strong>
        </a>
    </div>
    <div id="collapseOne" class="accordion-body collapse in">
        <div class="accordion-inner">
            Content
        </div>
    </div>
</div>
Martin Wickman
fonte
2
Eu realmente gostei dessa abordagem, Martin. Especialmente porque é muito discreto.
J Castillo
4
Achei que isso funcionava com uma exceção - o acento circunflexo inicial sempre é exibido expandido para todas as seções. Depois de expandir e recolher novamente, está correto.
Robb Sadler
8
@Robb - incluí a classe "recolhida" no meu elemento "recolhido" no html para resolver o problema com a seta inicial. Meu html é um pouco diferente, mas provavelmente funcionará
Marcos B
1
Eu gosto da solução css também. Alguns de meus colegas se sentem mais confortáveis ​​com css do que javascript, então essa foi a melhor solução para minha equipe. Obrigado por abordar a parte de inicialização. Agora funciona muito bem!
Hcabnettek
42

O Bootstrap Collapse tem alguns eventos aos quais você pode reagir:

$(document).ready(function(){    
    $('#accordProfile').on('shown', function () {
       $(".icon-chevron-down").removeClass("icon-chevron-down").addClass("icon-chevron-up");
    });

    $('#accordProfile').on('hidden', function () {
       $(".icon-chevron-up").removeClass("icon-chevron-up").addClass("icon-chevron-down");
    });
});
Philipp Hofmann
fonte
1
Muffls, você é uma estrela! agradável e simples também, obrigado por isso ;-)
Darren
1
de nada! você também pode usar mostrar ou ocultar em vez de mostrado e oculto. Experimente. Você verá qual você prefere.
Philipp Hofmann
1
Olá Muffs, alguma ideia de por que isso não funciona no meu site de teste ao vivo? datascrew.co.uk/gordonedge.com
Darren
add $ (document) .ready (... em você main.js coloquei o código acima.
Philipp Hofmann
8
Bootstrap3: os nomes dos eventos precisam ter .bs.collapse, para que estejam ativados ('hide.bs.collapse') e ('show.bs.collapse') ou exibidos / ocultos quando você quiser adicionar mais transições css ao isto.
Langeleppel
21

Use o pseudo-seletor CSSes: depois de usar os glifos integrados do Bootstrap 3 para uma resposta sem JS com pequenas modificações em seu HTML ...

CSS

.panel-heading [data-toggle="collapse"]:after
{
    font-family: 'Glyphicons Halflings';
    content: "\e072"; /* "play" icon */
    float: right;
    color: #b0c5d8;
    font-size: 18px;
    line-height: 22px;

    /* rotate "play" icon from > (right arrow) to down arrow */
    -webkit-transform: rotate(-90deg);
    -moz-transform:    rotate(-90deg);
    -ms-transform:     rotate(-90deg);
    -o-transform:      rotate(-90deg);
    transform:         rotate(-90deg);
}
.panel-heading [data-toggle="collapse"].collapsed:after
{
    /* rotate "play" icon from > (right arrow) to ^ (up arrow) */
    -webkit-transform: rotate(90deg);
    -moz-transform:    rotate(90deg);
    -ms-transform:     rotate(90deg);
    -o-transform:      rotate(90deg);
    transform:         rotate(90deg);
}

HTML

Adicione class="collapsed"a quaisquer tags âncora que são fechadas por padrão.

Isso transformará âncoras como

<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">

para dentro

<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">

Exemplo Live CodePen

http://codepen.io/anon/pen/VYobER

Captura de tela

Como aparece no JSBin

Bafromca
fonte
1
este link jsbin foi relatado
Nick Bartlett
2
Movido para CodePen. Obrigado por relatar. De uma chance!
bafromca
16

Adicionado à resposta @muffls para que funcione com todo o colapso do bootstrap do Twitter e faça a mudança na seta antes do início da animação.

$('.collapse').on('show', function(){
    $(this).parent().find(".icon-chevron-left").removeClass("icon-chevron-left").addClass("icon-chevron-down");
}).on('hide', function(){
    $(this).parent().find(".icon-chevron-down").removeClass("icon-chevron-down").addClass("icon-chevron-left");
});

Dependendo de sua estrutura HTML, você pode precisar modificar o parent().

João magnólia
fonte
1
+1 caiu e funcionou para mim - apenas modificado para usar icon-chevron-right em vez de left
azcoastal
1
Este funciona para mim. Outros códigos mudam a classe de todas as guias quando clicados em vez da guia clicada :)
vignesh
10

Acho que os melhores códigos são estes:

  $('#accordion1').collapse({
    toggle: false
  }).on('show',function (e) {
        $(e.target).parent().find(".icon-chevron-down").removeClass("icon-chevron-down").addClass("icon-chevron-up");
      }).on('hide', function (e) {
        $(e.target).parent().find(".icon-chevron-up").removeClass("icon-chevron-up").addClass("icon-chevron-down");
      });
user2273425
fonte
2
Esta é a única solução de trabalho para mim, alterne a classe de todos os grupos de acordeão. Saúde :)
maximus ツ
6

Se alguém estiver interessado, é assim que você faz com BS3, uma vez que alterou os nomes dos eventos:

$('.collapse').on('show.bs.collapse', function(){
  var i = $(this).parent().find('i')
  i.toggleClass('fa-caret-right fa-caret-down');
}).on('hide.bs.collapse', function(){
  var i = $(this).parent().find('i')
  i.toggleClass('fa-caret-down fa-caret-right');
});

Você simplesmente altera os nomes das classes no exemplo para aqueles que usa no seu caso.

rbsthlm
fonte
1
Obrigado b3rgstrom, apreciado. Vou verificar isso na próxima vez que usar o BS3.
Darren
1
Sem problemas, pensei que alguém poderia encontrar sua pergunta no futuro com o mesmo problema :)
rbsthlm
5

A solução CSS-only mais legível provavelmente seria usar o atributo aria expandido. Lembre-se de que você precisará adicionar aria-extended = "false" a todos os elementos de recolhimento, pois isso não é definido no carregamento (apenas no primeiro clique).

O HTML:

<h2 data-toggle="collapse" href="#collapseId" aria-expanded="false">
    <span class="glyphicon glyphicon-chevron-right"></span>
    <span class="glyphicon glyphicon-chevron-down"></span> Title
</h2>

O CSS:

h2[aria-expanded="false"] span.glyphicon-chevron-down,
h2[aria-expanded="true"] span.glyphicon-chevron-right
{
    display: none;
}

h2[aria-expanded="true"] span.glyphicon-chevron-down,
h2[aria-expanded="false"] span.glyphicon-chevron-right
{
    display: inline;
}

Funciona com Bootstrap 3.x.

Andreas Bergström
fonte
1
Isso funciona perfeitamente. Como minha tag âncora era o data-toggle, eu simplesmente alterei h2 para a no CSS
MC9000
3

Aqui está minha solução, que foi refinada a partir de uma postada por @ john-magnolia e resolve alguns de seus problemas

/**
 * Toggle on/off arrow for Twitter Bootstrap collapsibles.
 *
 * Multi-collapsible-friendly; supports several collapsibles in the same group, on the same page.
 */
function animateCollapsibles() {

    $('.collapse').on('show', function() {
        var $t = $(this);
        var header = $("a[href='#" + $t.attr("id") + "']");
        header.find(".icon-chevron-right").removeClass("icon-chevron-right").addClass("icon-chevron-down");
    }).on('hide', function(){
        var $t = $(this);
        var header = $("a[href='#" + $t.attr("id") + "']");
        header.find(".icon-chevron-down").removeClass("icon-chevron-down").addClass("icon-chevron-right");
    });
}

E aqui está o exemplo de marcação:

<div class="accordion" id="accordion-send">
    <div class="accordion-group">
        <div class="accordion-heading">
            <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion-send" href="#collapse-refund">
                <i class="icon icon-chevron-right"></i> Send notice
            </a>
        </div>
        <div id="collapse-refund" class="accordion-body collapse">
            <div class="accordion-inner">
                <p>Lorem ipsum Toholampi city</p>
            </div>
        </div>
    </div>
</div>
Mikko Ohtamaa
fonte
1
Boas pessoas - eu me sinto um grande idiota, mas não consigo fazer nenhuma dessas soluções funcionar: -S a única diferença que posso pensar é que eu uso o novo bootstrap3 e, portanto, obtenho as classes "glyphicon glyphicon-chevron-right. Qualquer ponteiros?
benteh
2
Bootstrap 3 não é uma versão compatível com versões anteriores. Consulte a documentação do Bootstrap 3 para saber como migrar o código.
Mikko Ohtamaa
1
Olá, Mikko, obrigado, sim, percebi isso e tive uma boa ajuda aqui: stackoverflow.com/questions/18147338/…
benteh
3

Uma solução bootstrap v3 (onde os eventos têm nomes diferentes), também usando apenas um seletor jQuery (como visto aqui ):

$('.accordion').on('hide.bs.collapse show.bs.collapse', function (n) {
    $(n.target).siblings('.panel-heading').find('i.glyphicon').toggleClass('glyphicon-chevron-down glyphicon-chevron-up');
});
Geert
fonte
Resposta excelente
Naveen DA
3

É assim que eu faço sem nenhum js.

Usei o ícone glyphicon-triangle-right mas funciona com qualquer outro ícone, o que ele faz é aplicar uma rotação de 90 graus ao ícone quando o painel está aberto ou não. estou a usar Bootstrap 3.3.5 para este.

Código CSS

h4.panel-title a {
    display: block;

}
h4.panel-title a.collapsed .glyphicon-triangle-right {
        color: #ada9a9 !important;
        transform: rotate(0deg);
}
h4.panel-title a .glyphicon-triangle-right {
        color: #515e64 !important;
        transform: rotate(90deg);
}

Esta é a estrutura HTML retirada do exemplo Bootstrap

<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
                            <div class="panel panel-default">
                                <div class="panel-heading" role="tab" id="headingOne">
                                    <h4 class="panel-title">
                                        <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
                                            Proven Expertise
                                            <span class="glyphicon glyphicon-triangle-right pull-right" aria-hidden="true"></span>
                                        </a>
                                    </h4>
                                </div>
                                <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
                                    <div class="panel-body">
                                        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
                                    </div>
                                </div>
                            </div>

                        </div>
Elétrica geral
fonte
Este método funciona para mim, mas o status inicial é girado em 90 graus. Você poderia gentilmente sugerir como tornar o status inicial não girado (0deg)? Obrigado!
Tsung-Ting Kuo
1
Nos elementos âncora, adicione a classe = "recolhido" para evitar o que está acontecendo com você
General Electric
Obrigado pela resposta! Na verdade, tentei '<h4 class = "panel-title collapsed">', mas não tive sorte. Isso seria correto?
Tsung-Ting Kuo
1
Tem que estar na tag âncora porque é o que o bootstrap js muda quando o evento onClick é disparado, verifique nesta página, está trabalhando com a solução que mencionei acubavoy.com/preguntas-frequentes
General Electric
2

Nenhuma das opções acima funcionou para mim, mas eu vim com isso e funcionou:

function toggleChevron(el) {
  if ($(el).find('i').hasClass('icon-chevron-left'))
      $(el).find('.icon-chevron-left').removeClass("icon-chevron-left").addClass("icon-chevron-down");
  else 
      $(el).find('.icon-chevron-down').removeClass("icon-chevron-down").addClass("icon-chevron-left");
}

Implementação de HTML:

<div class="accordion" id="accordion-send">
  <div class="accordion-group">
    <div class="accordion-heading" onClick="toggleChevron(this)">
      <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion-send" href="#collapse-refund">
        <i class="icon icon-chevron-right"></i> Send notice
      </a>
      ...
Joshua Benson
fonte
1

@RobSadler:

Versão CSS de RE Martin Wickman ...

Você pode contornar esse problema colocando acordeão-acento circunflexo na tag âncora e atribuindo a ela uma classe recolhida por padrão. Igual a:

<div class="accordion-group">
<div class="accordion-heading">
    <a class="accordion-toggle accordion-caret collapsed" data-toggle="collapse" href="#collapseOne">
        <strong>Header</strong>
    </a>
</div>
<div id="collapseOne" class="accordion-body collapse in">
    <div class="accordion-inner">
        Content
    </div>
</div>

Isso funcionou para mim.

RioBrewster
fonte
1

Para Bootstrup 3.2 + FontAwesome

$(document).ready(function(){    
    $('#accordProfile').on('shown.bs.collapse', function () {
       $(".fa-chevron-down").removeClass("fa-chevron-down").addClass("fa-chevron-up");
    });

    $('#accordProfile').on('hidden.bs.collapse', function () {
       $(".fa-chevron-up").removeClass("fa-chevron-up").addClass("fa-chevron-down");
    });
});

Às vezes você tem que escrever assim. Se então

$('.collapsed span').removeClass('fa-minus').addClass('fa-plus');

Gerado automaticamente (classe = "recolhido"), quando você pressiona o menu ocultar.

ps quando você precisa criar um menu em árvore

Popov Andrey
fonte
1

Isso foi respondido de várias maneiras, mas o que eu descobri foi o mais simples e fácil para mim com Bootstrap 3 e fontes incríveis. eu apenas fiz

$('a.toggler').on('click', function () {$('i', this).toggleClass('fa-caret-up');});

Isso apenas alterna a classe CSS do ícone que desejo mostrar. Eu adiciono o alternador de classe ao item ao qual desejo aplicar isso. Isso pode ser adicionado a qualquer item para o qual você deseja alternar um ícone.

Micah Montoya
fonte
0

Outra solução sem javascript que usa a própria funcionalidade de recolhimento:

/* Prevent block display and transition animation */
.expand-icon.collapse.in,
.collapse-icon.collapse.in {
  display: inline; }
.expand-icon.collapsing {
  display: none; }

/* HTML Toggler with glyphicons */
<a data-toggle="collapse" href=".my-collapse">
 <span class="my-collapse collapse-icon collapse in">
  <span class="glyphicon glyphicon-collapse-up"></span>
 </span>
 <span class="my-collapse expand-icon collapse">
  <span class="glyphicon glyphicon-expand"></span>   
 </span>
</a>
Sebastian Sangervasi
fonte
0

Para uma solução somente CSS (e sem ícones) usando Bootstrap 3, tive que mexer um pouco com base na resposta de Martin Wickman acima.

Eu não usei a notação acordeão- * porque ela é feita com painéis no BS3.

Além disso, tive que incluir no HTML inicial aria-extended = "true" no item que é aberto no carregamento da página.

Aqui está o CSS que usei.

.accordion-toggle:hover { text-decoration: none; }
.accordion-toggle:hover span, .accordion-toggle:hover strong { text-decoration: underline; }
.accordion-toggle:before { font-size: 25px; }
.accordion-toggle[data-toggle="collapse"]:before { content: "+"; margin-right: 0px; }
.accordion-toggle[aria-expanded="true"]:before { content: "-"; margin-right: 0px; }

Aqui está meu HTML higienizado:

<div id="acc1">    
    <div class="panel panel-default">
        <div class="panel-heading">
            <span class="panel-title">
                <a class="accordion-toggle" data-toggle="collapse" aria-expanded="true" data-parent="#acc1" href="#acc1-1">Title 1
                    </a>
            </span>
        </div>
        <div id=“acc1-1 class="panel-collapse collapse in">
            <div class="panel-body">
                Text 1
            </div>
        </div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">
            <span class="panel-title">
                <a class="accordion-toggle" data-toggle="collapse" data-parent="#acc1 href=“#acc1-2”>Title 2
                    </a>
            </span>
        </div>
        <div id=“acc1-2 class="panel-collapse collapse">
            <div class="panel-body">
                Text 2                  
            </div>
        </div>
    </div>
</div>
JessycaFrederick
fonte
0

Resposta mais curta possível.

HTML

<a data-toggle="collapse" data-parent="#panel-quote-group" href="#collapseQuote">
    <span class="toggle-icon glyphicon glyphicon-collapse-up"></span>
</a>

JS:

<script type="text/javascript">
 $(function () {
     $('a[data-toggle="collapse"]').click(function () {
     $(this).find('span.toggle-icon').toggleClass('glyphicon-collapse-up glyphicon-collapse-down');
     })
 })
 </script>

E, claro, você pode usar qualquer coisa para um seletor em vez de uma tag âncora ae também pode usar um seletor específico em vez de thisse o ícone estiver fora do elemento clicado.

Junaid
fonte
0

Aqui está uma solução que cria uma seção que é expansível usando um pouco de material design, bootstrap 4.5 / 5 alpha e totalmente não-javascript.

Estilo para a seção da cabeça

<style>
[data-toggle="collapse"] .fa:before {
    content: "\f077";
}

[data-toggle="collapse"].collapsed .fa:before {
    content: "\f078";
}
</style>

Body html

<div class="pt-3 pb-3" style="border-top: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; cursor: pointer;">
<a href="#expandId" class="text-dark float-right collapsed" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="expandId">
    <i class="fa" aria-hidden="false"></i>
</a>
<a href="#expandId" class="text-dark collapsed" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="expandId">Expand Header</a>
<div class="collapse" id="expandId">
    CONTENT GOES IN HERE
</div>
William Worley
fonte