Agregar un ícono abierto / cerrado a los plegables de Twitter Bootstrap (acordeones)

87

Configuré esta versión simple del acordeón Bootstrap :

Acordeón simple: http://jsfiddle.net/darrenc/cngPS/

Actualmente, el ícono solo apunta hacia abajo , pero ¿alguien sabe qué JS se necesitaría para implementar para cambiar la clase del ícono a:

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

... para que apunte hacia arriba cuando se expanda y cambie de nuevo a abajo cuando se colapsa, y entonces ¿cuarto?

Darren
fuente

Respuestas:

94

Aquí está la respuesta para aquellos que buscan una solución en Bootstrap 3 (como yo).

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

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

Acordeón de ejemplo:

Ejemplo de acordeón bootply

Andrei Veve
fuente
6
exactamente lo que se necesita para bootstrap 3.x. si usa 2.x, elimine .bs.collapse. También cambié shown and hidden to show and hidepara que la animación ocurra antes de que se abra el acordeón.
user1881482
2
esta debería ser la respuesta correcta porque también se ejecuta en la versión 4
Andrés Felipe
¿Qué tal los acordeones anidados? los elementos secundarios no tienen galones, pero todavía estoy activando el interruptor principal.
esotérico
48

Aquí está mi enfoque para Bootstrap 2.x. Es solo un css. No se necesita 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;
    }

Simplemente agregue class accordion-caret al div accordion-group, así:

<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
fuente
2
Me gustó mucho este enfoque Martin. Especialmente porque es muy discreto.
J Castillo
4
Descubrí que esto funciona con una excepción: el signo de intercalación inicial siempre se muestra expandido para todas las secciones. Una vez que se expande y luego se colapsa nuevamente, es correcto.
Robb Sadler
8
@Robb - Incluí la clase "colapsado" en mi elemento "colapso" en el html para resolver el problema con la flecha inicial. Mi html es un poco diferente pero probablemente funcionará
Mark B
1
También me gusta la solución css. Algunos de mis compañeros se sienten más cómodos con CSS que con JavaScript, por lo que esta fue una mejor solución para mi equipo. Gracias por abordar la parte de inicialización. ¡Ahora funciona muy bien!
Hcabnettek
42

Bootstrap Collapse tiene algunos eventos a los que puede reaccionar:

$(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
fuente
1
Muffls, eres una estrella! agradable y simple también, gracias por eso ;-)
Darren
1
¡De nada! también puede usar mostrar u ocultar en lugar de mostrar y ocultar. Pruébalo. Verás cuál prefieres.
Philipp Hofmann
1
Hola Muffs, ¿alguna idea de por qué esto no funcionará en mi sitio de prueba en vivo? datascrew.co.uk/gordonedge.com
Darren
agregue $ (document) .ready (... en su main.js he puesto el código de arriba.
Philipp Hofmann
8
Bootstrap3: los nombres de los eventos deben tener .bs.collapse, por lo que están en ('hide.bs.collapse') y en ('show.bs.collapse'), o se muestran / ocultan cuando desea agregar más transiciones CSS a eso.
Langeleppel
21

Use el pseudo-selector de CSSes: después de usar los Glyphicons integrados de Bootstrap 3 para una respuesta sin JS con una pequeña modificación en su 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

Agregue class="collapsed"a cualquier etiqueta de anclaje que esté cerrada de forma predeterminada.

Esto convertirá anclas como

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

dentro

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

Ejemplo de CodePen Live

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

Captura de pantalla

Cómo aparece en JSBin

bafromca
fuente
1
este enlace jsbin ha sido informado
Nick Bartlett
2
Lo moví a CodePen. Gracias por informarnos. ¡Darle una oportunidad!
bafromca
16

Se agregó a la respuesta de @muffls para que esto funcione con todo el colapso de bootstrap de Twitter y realice el cambio en la flecha antes de que comience la animación.

$('.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");
});

Dependiendo de su estructura HTML, es posible que deba modificar el archivo parent().

John Magnolia
fuente
1
+1 lo dejó caer y funcionó para mí, solo modificado para usar icon-chevron-right en lugar de left
azcoastal
1
Esta funciona para mí. Otros códigos cambian de clase para todas las pestañas cuando se hace clic en él en lugar de en la pestaña en la que se hace clic :)
vignesh
10

Creo que los mejores códigos son estos:

  $('#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");
      });
usuario2273425
fuente
2
Esta es la única solución que funciona para mí, el resto cambia la clase de todos los grupos de acordeón. Saludos :)
maximus ツ
6

Si alguien está interesado, así es como se hace con BS3 ya que cambiaron los nombres de los 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');
});

Simplemente cambie los nombres de las clases en el ejemplo por los que usa en su caso.

rbsthlm
fuente
1
Gracias b3rgstrom, apreciado. Lo comprobaré la próxima vez que use BS3.
Darren
1
Sin problemas, pensé que alguien podría encontrar su pregunta en el futuro con el mismo problema :)
rbsthlm
5

La solución de solo CSS más legible probablemente sería usar el atributo aria-extended. Recuerde que deberá agregar aria-extended = "false" a todos los elementos de colapso ya que esto no está configurado en la carga (solo en el primer clic).

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

El 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 con Bootstrap 3.x.

Andreas Bergström
fuente
1
Esto funciona perfectamente. Debido a que mi etiqueta de anclaje era el cambio de datos, simplemente cambié el h2 a a en el CSS
MC9000
3

Aquí está mi solución, que se refina aún más de una publicada por @ john-magnolia y resuelve algunos de sus 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");
    });
}

Y aquí está el marcado de ejemplo:

<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
fuente
1
Buena gente, me siento como un gran idiota, pero no puedo hacer que ninguna de estas soluciones funcione: -La única diferencia en la que puedo pensar es que uso el nuevo bootstrap3 y, por lo tanto, obtengo las clases "glyphicon glyphicon-chevron-right. Cualquiera punteros?
benteh
2
Bootstrap 3 no es una versión compatible con versiones anteriores. Consulte la documentación de Bootstrap 3 sobre cómo migrar el código.
Mikko Ohtamaa
1
Hola, Mikko, gracias, sí, lo
recopilé
3

Una solución bootstrap v3 (donde los eventos tienen diferentes nombres), también usando solo un selector de jQuery (como se ve aquí ):

$('.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
fuente
Excelente respuesta
Naveen DA
3

Así es como lo hago sin js.

Usé el icono glyphicon-triangle-right pero funciona con cualquier otro icono, lo que hace es que aplica una rotación de 90 grados al icono cuando el panel está abierto o no. Estoy usando 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 es la estructura HTML tomada del ejemplo de 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>
Energia General
fuente
Este método funciona para mí, pero el estado inicial se rota en 90 grados. ¿Podría sugerirnos amablemente cómo hacer que el estado inicial no esté rotado (0 grados)? ¡Gracias!
Tsung-Ting Kuo
1
En los elementos de anclaje, agregue class = "collapsed" para evitar lo que le está sucediendo
General Electric
¡Gracias por la respuesta! De hecho, probé '<h4 class = "panel-title collapsed">' pero no tuve suerte. ¿Sería esto correcto?
Tsung-Ting Kuo
1
Tiene que estar en la etiqueta de anclaje porque es lo que cambia bootstrap js cuando se activa el evento onClick, verifique en esta página, está funcionando con la solución que mencioné acubavoy.com/preguntas-frequentes
General Electric
2

Nada de lo anterior funcionó para mí, pero se me ocurrió esto y funcionó:

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

Implementación 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
fuente
1

@RobSadler:

RE Versión única de CSS de Martin Wickman ...

Puede solucionar ese problema colocando un signo de intercalación de acordeón en la etiqueta de anclaje y dándole una clase contraída de forma predeterminada. Al igual que:

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

Eso funcionó para mí.

Río Brewster
fuente
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");
    });
});

A veces tienes que escribir así. Si es así

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

Generado automáticamente (clase = "contraído"), al presionar el menú Ocultar.

ps cuando necesita crear un menú de árbol

Popov Andrey
fuente
1

Esto ha sido respondido de muchas maneras, pero lo que se me ocurrió fue la más simple y fácil para mí con Bootstrap 3 y una fuente increíble. Lo acabo de hacer

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

Esto simplemente cambia la clase CSS del icono que quiero mostrar. Agrego el conmutador de clase al elemento al que quiero aplicar esto. Esto se puede agregar a cualquier elemento del que desee alternar un icono.

Micah Montoya
fuente
0

Otra solución sin JavaScript que utiliza la función de contracción en sí misma:

/* 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>
Sebastián Sangervasi
fuente
0

Para una solución solo de CSS (y sin íconos) usando Bootstrap 3, tuve que manipular un poco según la respuesta de Martin Wickman anterior.

No utilicé la notación acordeón- * porque se hace con paneles en BS3.

Además, tuve que incluir en el HTML inicial aria-extended = "true" en el elemento que está abierto al cargar la página.

Aquí está el CSS que utilicé.

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

Aquí está mi HTML desinfectado:

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

Respuesta más corta posible.

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>

Y, por supuesto, puede usar cualquier cosa para un selector en lugar de una etiqueta de anclaje ay también puede usar un selector específico en lugar de thissi su icono se encuentra fuera del elemento en el que se hizo clic.

Junaid
fuente
0

Aquí hay una solución que crea una sección que se puede expandir usando un diseño de material, bootstrap 4.5 / 5 alpha y completamente sin JavaScript.

Estilo para la sección de la cabeza

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

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

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