I have nested Bootstrap Accordions where I want to scroll to the top of the item expanded. The problem is, expanded sub-items higher up in the DOM cause problems locating the item that's actually being expanded.
I've searched through all the posts that mention this, but my code looks very different to those and I can't get it working.
Can anyone help me automatically close all sub-items if a parent gets collapsed due to another parent being expanded?
UPDATED CODE WITH WORKING VERSION:
$(function () {
$('.panel-group').on('shown.bs.collapse', function (e) {
var offset = $(this).find('.collapse.in').prev('.panel-heading');
if(offset) {
$('html,body').animate({
scrollTop: $(offset).offset().top -6
}, 500);
e.stopPropagation();
}
});
$('.panel-collapse').on('hidden.bs.collapse', function () {
// find the children and close them
$(this).find('.collapse.in').collapse('hide');
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<p> </p>
<p> </p>
<div class="panel-group level1" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading1">
<h4 class="panel-title">
<a role="button" class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapse1" aria-expanded="true" aria-controls="collapse1">
Item 1
</a>
</h4>
</div>
<div id="collapse1" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading1">
<div class="panel-body">
<div class="panel-group level2" id="accordion1" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading1_1">
<h4 class="panel-title">
<a role="button" class="collapsed" data-toggle="collapse" data-parent="#accordion1" href="#collapse1_1" aria-expanded="true" aria-controls="collapse1_1">
Item 1.1
</a>
</h4>
</div>
<div id="collapse1_1" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading1_1">
<div class="panel-body">
Lorem ipsum ...
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading1_2">
<h4 class="panel-title">
<a role="button" class="collapsed" data-toggle="collapse" data-parent="#accordion1" href="#collapse1_2" aria-expanded="true" aria-controls="collapse1_2">
Item 1.2
</a>
</h4>
</div>
<div id="collapse1_2" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading1_2">
<div class="panel-body">
Lorem ipsum ...
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading2">
<h4 class="panel-title">
<a role="button" class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapse2" aria-expanded="true" aria-controls="collapse2">
Item 2
</a>
</h4>
</div>
<div id="collapse2" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading2">
<div class="panel-body">
<div class="panel-group level2" id="accordion2" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading2_1">
<h4 class="panel-title">
<a role="button" class="collapsed" data-toggle="collapse" data-parent="#accordion2" href="#collapse2_1" aria-expanded="true" aria-controls="collapse2_1">
Item 1.1
</a>
</h4>
</div>
<div id="collapse2_1" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading2_1">
<div class="panel-body">
Lorem ipsum ...
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading2_2">
<h4 class="panel-title">
<a role="button" class="collapsed" data-toggle="collapse" data-parent="#accordion2" href="#collapse2_2" aria-expanded="true" aria-controls="collapse2_2">
Item 1.2
</a>
</h4>
</div>
<div id="collapse2_2" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading2_2">
<div class="panel-body">
Lorem ipsum ...
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
See attached code to replicate problem:
Thanks in advance, Justin
Bootstrap 5 (Update 2023)
jQuery is no longer native to Bootstrap 5 so vanilla JS will achieve the same functionality to close the children...
const myCollapsible = document.getElementById('module-test')
myCollapsible.addEventListener('hidden.bs.collapse', event => {
// close children
event.target.querySelectorAll('.collapse').forEach(element => {
const bc = bootstrap.Collapse.getOrCreateInstance(element)
bc.hide()
})
})
https://codeply.com/p/mJYXqUDGm6
Bootstrap 3 (Original Answer)
It should be as simple as handling the hidden
event..
$('.panel-collapse').on('hidden.bs.collapse', function () {
// find the children and close them
$(this).find('.collapse').collapse('hide');
});
Bootstrap 3: https://codeply.com/p/MGamArJJ7I