I am trying to mimic the Outlook bar using Twitter bootstrap using the accordion and collapse plugin, so far I got the collapse and accordion working, but it presently allows for all sections to be collapsed.
I would like to limit it so that one and only one is always shown.
Here is the one I am working on: http://jsfiddle.net/trajano/SMT9D/ and I think it's somewhere along the lines of
$('#accordions').on('hide', function (event) {
console.warn("HIDE TRIGGERED, check if trying to hide the active one if so stop");
})
Just add data-toggle="collapse" and a data-target to element, to automatically assign control of a collapsible element. The data-target attribute accepts a CSS selector to apply the collapse to. Be sure to add the class collapse to the collapsible element.
If you are using bootstrap accordion and want that one of the accordion should be opened for the first time so add class="in" .
Close all opened tabs before opening selected tab. This will prevent multiple tabs from being open at one time.
To create an accordion that is collapsed by default, we need to set the 'active' property of the jQuery Accordion as false. Syntax: $("#demoAccordion"). accordion({ collapsible: true, active: false});
Here is an easy way to do it:
$('.accordion .btn-link').on('click', function(e) {
if (!$(this).hasClass('collapsed')) {
e.stopPropagation();
}
});
from @mr_joncollette in the comments
JsFiddle for Bootstrap 3.
Code for Bootstrap 3:
$('.panel-heading a').on('click',function(e){
if($(this).parents('.panel').children('.panel-collapse').hasClass('in')){
e.stopPropagation();
}
// You can also add preventDefault to remove the anchor behavior that makes
// the page jump
// e.preventDefault();
});
The code checks if the clicked element is the one that is currently shown (by the class "in") and if it does have the "in" class, it stops the hiding process.
JsFiddle for Bootstrap 2.
Code for Bootstrap 2:
$('.accordion-toggle').on('click',function(e){
if($(this).parents('.accordion-group').children('.accordion-body').hasClass('in')){
e.stopPropagation();
}
// You can also add preventDefault to remove the anchor behavior that makes
// the page jump
// e.preventDefault();
});
Note: Be careful if you want to attach more click events on the accordion, since the e.stopPropagation()
will block events that would occur after the check.
I want to precise @Hugo Dozois 's answer
http://jsfiddle.net/SMT9D/61/
You should add e.preventDefault();
to prevent the default behaviour of #
HTML anchor if you have a scroll in your page
$('.panel-heading a').on('click',function(e){
if($(this).parents('.panel').children('.panel-collapse').hasClass('in')){
e.preventDefault();
e.stopPropagation();
}
});
Updated 2018
Here's how to keep at least open in both Bootstrap v3 or v4. This means that the open accordion can only be closed by toggling another one open.
Bootstrap 4
https://www.codeply.com/go/bbCcnl0jBB
// the current open accordion will not be able to close itself
$('[data-toggle="collapse"]').on('click',function(e){
if ( $(this).parents('.accordion').find('.collapse.show') ){
var idx = $(this).index('[data-toggle="collapse"]');
if (idx == $('.collapse.show').index('.collapse')) {
e.stopPropagation();
}
}
});
Also, see this answer which shows how to specify a "default" accordion that will open when all others are closed.
Bootstrap 3
$('[data-toggle="collapse"]').on('click',function(e){
if($(this).parents('.panel').find('.collapse').hasClass('in')){
var idx = $(this).index('[data-toggle="collapse"]');
var idxShown = $('.collapse.in').index('.accordion-body');
if (idx==idxShown) {
e.stopPropagation();
}
}
});
https://www.codeply.com/go/yLw944BrgA
<div class="accordion" id="myAccordion">
<div class="panel">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-1" data-parent="#myAccordion">Question 1?</button>
<div id="collapsible-1" class="collapse">
..
</div>
</div>
<div class="panel">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-2" data-parent="#myAccordion">Question 2?</button>
<div id="collapsible-2" class="collapse">
..
</div>
</div>
<div class="panel">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-3" data-parent="#myAccordion">Question 3?</button>
<div id="collapsible-3" class="collapse">
...
</div>
</div>
</div>
(Note: the panel
class is needed in Bootstrap 3 to make the accordion behavior work)
Or you can use simple CSS trick as follows:
/*
prevent the active panel from collapsing
*/
.panel-group [aria-expanded=true]{
/*
http://caniuse.com/#feat=pointer-events
Works for MOST modern browsers. (- Opera Mobile)
*/
pointer-events: none;
}
must have proper tags on the inactive panel links
aria-expanded="false"
As all the other JS answers use an inadvisable stopPropagation()
here is my solution using just the native Bootstrap events (tested on Bootstrap 4).
JsFiddle
$('#accordionExample').on('show.bs.collapse', function () {
$(this).data('isShowing', true);
});
$('#accordionExample').on('hide.bs.collapse', function (event) {
if (!$(this).data('isShowing')) {
event.preventDefault();
}
$(this).data('isShowing', false);
});
It makes use of the fact that a click on a collapsed element will result in a show.bs.collapse
followed by a hide.bs.collapse
. Whereas a click on the open element will result in just a hide.bs.collapse
.
I have a scenario that do not fit with any posted answer: multiple accordions on the same page and some other collapsible components that are not accordions (without data-parent
attribute).
$("[data-toggle=collapse][data-parent]").click(function (e) {
var button = $(this);
var parent = $(button.attr("data-parent"));
var panel = parent.find(button.attr("href") || button.attr("data-target"));
if (panel.hasClass("in")) {
e.preventDefault();
e.stopPropagation()
}
});
This code only triggers on accordions, since checks data-parent
attribute.
It also does not assume a card
(or panel
for bootstrap 3) structure, it uses the same attributes that bootstrap api.
I hope it helps.
Bootstrap 5
Omit the data-bs-parent
attribute on each .accordion-collapse
to make accordion items stay open when another item is opened.
Solution for Bootstrap-5
$(this).on('mouseenter', function (e) {
if( !$(this).hasClass('collapsed')) {
$(this).attr('data-bs-toggle','disabled');
}
})
$(this).on('mouseleave', function (e) {
if( !$(this).hasClass('collapsed')) {
$(this).attr('data-bs-toggle','collapse');
}
})
Hope it helps Andreas
Bootstrap 5
Alternate solution from @awant. This time using the collapse events to disable the button. This works great with touch screens.
$(this).on('show.bs.collapse', function (e) {
$(buttonSelector).attr('data-bs-toggle','disabled');
})
$(this).on('hide.bs.collapse', function (e) {
$(buttonSelector).attr('data-bs-toggle','collapse');
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With