Twitter Bootstrap 3 - Auto expand accordion when link is clicked in another accordion
I have a page with various accordions. Some of these accordions refer to content in another accordion on the page, my question is how to make the other accordion expand in the first accordion.
I cannot get it to work.
I have set the link as <a href="#SubTitle2">Test</a>
And in the first <p>
under <div class="panel-body">
how <p id="SubTitle2">Content</p>
, but it does nothing.
Am I putting it in the wrong place, or am I completely wrong about this?
Below is my complete code
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<a class="accordion-toggle collapsed" data-parent="#accordion" href="#collapseOne" data-toggle="collapse">Heading 1</a>
</h3>
</div>
<div class="panel-collapse collapse" id="collapseOne">
<div class="panel-body">
<p><a href="#SubTitle2">Test</a></p>
</div>
</div>
</div>
</div>
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<a class="accordion-toggle collapsed" data-parent="#accordion" href="#collapseTwo" data-toggle="collapse">Heading 2</a>
</h3>
</div>
<div class="panel-collapse collapse" id="collapseTwo">
<div class="panel-body">
<p id="SubTitle2">Content</p>
</div>
</div>
</div>
</div>
source to share
Managed to make it work by mixing the answers of Nasir Mahmoud and Vebeno.
I basically mixed and matched both solutions and it works. My code now:
<p><a class="collapsed"
href="#SubTitle2"
data-toggle="collapse"
data-target="#collapseTwo">Test
</a></p>
Since you cannot mark the answers as an answer, I will add a comment to both of them
source to share
If you tend to use jQuery for this, you can do the following:
$('#SubTitle2').click(function(){
$('#collapseTwo').collapse('show');
});
... with setting the binding, something like this:
<a href="#" id="SubTitle2" data-target="#collapseTwo">Test</a>
You can check it out here: http://www.bootply.com/jQMOup05vG
source to share
None of the answers provided earlier are acceptable for my situation. I don't know in advance which links exist on the page and which links will require expanding the collapsed sections. I also have nested folding sections. Also, I want the extension to happen if someone links to a page from another document. So I ended up with a solution that dynamically detects which partitions should be open. When a click on the link I care about occurs, the handler:
-
Finds all target parents that are collapsed sections. (
$(target).parents(".collapse:not(.in)").toArray().reverse();
) -
Starting at the outermost parent, it requests the extension of that element. (These are calls
next()
. The call$parent.collapse('show');
is what the parent shows.) -
When an element expands, it expands to the next parent (closer to the target of the link). (
if (parents.length)...
) -
Until finally he asks to scroll the target. (
target.scrollIntoView(true);
)
At first I tried to traverse the DOM tree in reverse order, from innermost parent to outermost, but I got strange results. The results were inconsistent even with event bubble compensation. Requesting a scroll to the target is necessary as it is likely that the browser will scroll the window before expanding the sections.
Here is the code. win
and are doc
set to instances of Window
and Document
, which actually hold the DOM tree being processed. Since frames can be used simply by referencing Window
and Document
, this is not normal. A variable root
is this Element
that contains the part of the DOM that I care about.
function showTarget() {
var hash = win.location.hash;
if (!hash)
return;
var target = doc.getElementById(hash.slice(1));
if (!target)
return;
var parents =
$(target).parents(".collapse:not(.in)").toArray().reverse();
function next(parent) {
var $parent = $(parent);
$parent.one('shown.bs.collapse', function () {
if (parents.length) {
next(parents.shift());
return;
}
target.scrollIntoView(true);
});
$parent.collapse('show');
}
next(parents.shift());
}
win.addEventListener('popstate', showTarget);
$(root).on('click', 'a[href]:not([data-toggle], [href="#"])',
function (ev) {
setTimeout(showTarget, 0);
});
showTarget();
Notes:
-
The selector
a[href]:not([data-toggle], [href="#"])
limits the event, listening only to elementsa
that are actually hyperlinks to the rest of the document. Sometimesa
used for other purposes. For example, those elementsa
that have an attributedata-toggle
or havehref="#"
are not used for page navigation. -
setTimeout(showTarget, 0)
first enables the default action for clicking on the hyperlink (i.e. changing the hash) and then invokedshowTarget
. This works everywhere except FF. Several tests show thatshowTarget
it will not see a change in FF unless a timeout is set. 0ms doesn't work, 1ms doesn't, and 10ms doesn't work. Anyway, I would rather not hardcode a specific FF value that may change in the future, so we also listen to popstate` to catch cases that would not have been caught by FF. -
An explicit call is
showTarget()
required for cases where the page is loaded with a URL that has a hash. -
I tried an implementation that only listened to
popstate
, but turned out to be unreliable due to the way Chrome and FF differ in how they generatepopstate
. (Chrome generates it whenever the link is clicked, even if the hash doesn't change. FF only generates it when the hash changes.) -
This code has been tested in Chrome (39, 38, 36), FF (31) and IE (10, 11).
source to share
you have set group group id = accordion twice. This is not good. Wrap two panels in one group box with one ID:
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<a class="accordion-toggle collapsed" data-parent="#accordion" href="#collapseOne" data-toggle="collapse">Heading 1</a>
</h3>
</div>
<div class="panel-collapse collapse" id="collapseOne">
<div class="panel-body">
<p><a href="#SubTitle2">Test</a></p>
</div>
</div>
</div>
<!-- SNIP
</div>
<div class="panel-group" id="accordion">
SNAP -->
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<a class="accordion-toggle collapsed" data-parent="#accordion" href="#collapseTwo" data-toggle="collapse">Heading 2</a>
</h3>
</div>
<div class="panel-collapse collapse" id="collapseTwo">
<div class="panel-body">
<p id="SubTitle2">Content</p>
</div>
</div>
</div>
</div>
source to share