Idan Adar
Idan Adar

Reputation: 44516

How to scroll to an accordion *inside* an opened accordion?

I have the following structure (might have gotten the copy/paste wrong after the content reduction). It's basically a collapse element inside a collapse element.

I also have the following code, used to scroll to the opened accordion element once clicked:

$(".accordion").on("shown.bs.collapse", function() {
    var myEl = $(this).find('.collapse.in').prev('.panel-heading');
    $('html, body').animate({
        scrollTop: $(myEl).offset().top - 6
    }, 500);
});

This snippet works - as long as the accordion element does not have a child accordion. With the child accordion, what happens is that once opening the parent accordion and then the child accordion, it scrolls to the child element but then scrolls to the parent element.

What do I need to modify in the JavaScript snippet to get this working?
I'm pretty sure the current issue happens due to the use of .prev.

<div class="panel-group accordion" id="application-migration" role="tablist" aria-multiselectable="true">
    <div class="panel panel-default">
        <div class="panel-heading" role="tab" id="migrate-hybrid">
            <h4 class="panel-title">
                        <a role="button" data-toggle="collapse" data-parent="#hybrid-migration" href="#collapseMigrateHybrid" aria-expanded="false" aria-controls="collapseMigrateHybrid"> ... </a>
                    </h4>
        </div>

        <div id="collapseMigrateHybrid" class="panel-collapse collapse" role="tabpanel" aria-labelledby="migrate-hybrid">
            ...
            ...
            ...
            <div class="panel-group accordion" id="setupCordova" role="tablist" aria-multiselectable="false">
                <div class="panel panel-default">
                    <div class="panel-heading" role="tab" id="setupCordova">
                        <h4 class="panel-title">
                            <a class="preventScroll" role="button" data-toggle="collapse" data-parent="#setupCordova" data-target="#collapseCordova" aria-expanded="false" aria-controls="collapseCordova"> ... </a>
                        </h4>
                    </div>

                    <div id="collapseCordova" class="panel-collapse collapse" role="tabpanel" aria-labelledby="setupCordova">
                        <div class="panel-body">
                            ...
                            ...
                            ...
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Upvotes: 3

Views: 1221

Answers (1)

Gleb Kemarsky
Gleb Kemarsky

Reputation: 10398

Unfortunately, the shown.bs.collapse event is fired for both accordions when you open the child accordion.

UPD. You can avoid the second event by event.stopPropagation()

https://jsfiddle.net/glebkema/t1wqbxwh/

$(".accordion").on("shown.bs.collapse", function(e) {
    var myEl = $(this).find('.collapse.in').prev('.panel-heading');
    $('html, body').animate({
        scrollTop: $(myEl).offset().top - 6
    }, 500);
    e.stopPropagation();
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

<p>...</p>
<p>...</p>
<p>...</p>

<div class="panel-group accordion" id="application-migration" role="tablist" aria-multiselectable="true">
    <div class="panel panel-default">
        <div class="panel-heading" role="tab" id="migrate-hybrid">
            <h4 class="panel-title">
                        <a role="button" data-toggle="collapse" data-parent="#hybrid-migration" href="#collapseMigrateHybrid" aria-expanded="false" aria-controls="collapseMigrateHybrid"> ... </a>
                    </h4>
        </div>

        <div id="collapseMigrateHybrid" class="panel-collapse collapse" role="tabpanel" aria-labelledby="migrate-hybrid">
            <p>...</p>
            <p>...</p>
            <p>...</p>
            <div class="panel-group accordion" id="setupCordova" role="tablist" aria-multiselectable="false">
                <div class="panel panel-default">
                    <div class="panel-heading" role="tab" id="setupCordova">
                        <h4 class="panel-title">
                            <a class="preventScroll" role="button" data-toggle="collapse" data-parent="#setupCordova" data-target="#collapseCordova" aria-expanded="false" aria-controls="collapseCordova"> ... </a>
                        </h4>
                    </div>

                    <div id="collapseCordova" class="panel-collapse collapse" role="tabpanel" aria-labelledby="setupCordova">
                        <div class="panel-body">
                            <p>...</p>
                            <p>...</p>
                            <p>...</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<p>...</p>
<p>...</p>
<p>...</p>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

You can try to use a[aria-expanded="false"]' ).click

https://jsfiddle.net/glebkema/soc0rp3w/

$( 'a[aria-expanded="false"]' ).click(function() {
    $('html, body').animate({
        scrollTop: $(this).offset().top - 6
    }, 500);
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

<p>...</p>
<p>...</p>
<p>...</p>

<div class="panel-group accordion" id="application-migration" role="tablist" aria-multiselectable="true">
    <div class="panel panel-default">
        <div class="panel-heading" role="tab" id="migrate-hybrid">
            <h4 class="panel-title">
                        <a role="button" data-toggle="collapse" data-parent="#hybrid-migration" href="#collapseMigrateHybrid" aria-expanded="false" aria-controls="collapseMigrateHybrid"> ... </a>
                    </h4>
        </div>

        <div id="collapseMigrateHybrid" class="panel-collapse collapse" role="tabpanel" aria-labelledby="migrate-hybrid">
            <p>...</p>
            <p>...</p>
            <p>...</p>
            <div class="panel-group accordion" id="setupCordova" role="tablist" aria-multiselectable="false">
                <div class="panel panel-default">
                    <div class="panel-heading" role="tab" id="setupCordova">
                        <h4 class="panel-title">
                            <a class="preventScroll" role="button" data-toggle="collapse" data-parent="#setupCordova" data-target="#collapseCordova" aria-expanded="false" aria-controls="collapseCordova"> ... </a>
                        </h4>
                    </div>

                    <div id="collapseCordova" class="panel-collapse collapse" role="tabpanel" aria-labelledby="setupCordova">
                        <div class="panel-body">
                            <p>...</p>
                            <p>...</p>
                            <p>...</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<p>...</p>
<p>...</p>
<p>...</p>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

Upvotes: 2

Related Questions