Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Twitter bootstrap expand/collapse all - within bootstrap tabs

I am using Twitter Bootstrap's tabs to hold an accordion of FAQs within each tab. The requirement is to have an expand/collapse all button for each tab that expands/collapses the answers. I currently have the expand/collapse button working correctly for the first tab that loads. However, when I click another tab and execute the same button it does not work. When I click back to the initial tab that loads, it no-longer works either.

Here is the jsfiddle

HTML Below

<ul class="nav nav-tabs" id="tabFAQ">
        <li class="active"><a href="#GQ">General Questions</a></li>
        <li><a href="#ICQ">Insurance Coverage</a></li>
        <li><a href="#PQ">Payment</a></li>
        <li><a href="#FQ">Forms</a></li>
        <li><a href="#CQ">Claims</a></li>
    </ul>
    <div class="tab-content" id="faqContent">
        <div class="tab-pane active" id="GQ">
            <div class="accordion" id="generalQuestions">
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseOne_GQ">Q. What do I do if I’m having trouble logging in?</a>
                    </div>
                    <div id="collapseOne_GQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Please contact our Customer Care team at 800-821-7303 for assistance.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseTwo_GQ">Q. Will additional online services be added to this portal?</a>
                    </div>
                    <div id="collapseTwo_GQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes. We will be adding many online services to this portal over the next six months.  Please check back often.</div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseThree_GQ">Q. What information am I able to access on this portal?</a>
                    </div>
                    <div id="collapseThree_GQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. We currently have the ability to display any premiums that are currently due and allow you to make an immediate one-time payment from your checking account, savings account, Visa or MasterCard.  Your payment will be confirmed immediately.  Other functions are planned to be added to the portal over the next six months.  Check back often.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseFour_GQ">Q. Can I choose my own Username and Password?</a>
                    </div>
                    <div id="collapseFour_GQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, you can choose your own Username and Password.  We suggest using your email address for your Username, but any username that is between 8 and 20 characters long could be used.  A secure Password should be 8 to 20 characters long, with no spaces, and contains at least one special character.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseFive_GQ">Q. Can I update by email address online?</a>
                    </div>
                    <div id="collapseFive_GQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, but I have no idea how right now.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="ICQ">
            <div class="accordion" id="Div1">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne_ICQ">Q. Insurance Coverage question Stub for Later? </a> </div>
                        <div id="collapseOne_ICQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Answer stub for later.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="PQ">
        <div class="accordion" id="accordion3">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseOne_PQ">Q. When is my payment actually made to my account? </a> </div>
                        <div id="collapseOne_PQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Your payment is posted to your account within 24 hours after receipt of the funds.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseSeven_PQ">Q. What is a one-time payment? </a> </div>
                        <div id="collapseSeven_PQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. This is a web-based service that enables our customers to make a single payment to pay their insurance premium.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseEight_PQ">Q. How do I know my payments are secure? </a> </div>
                        <div id="collapseEight_PQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Our portal uses encryption software and hardware to protect your information. For more information, view our <a href="#">Privacy Policy</a>. </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseNine_PQ">Q. Can I use a debit card to make a one-time online payment? </a> </div>
                        <div id="collapseNine_PQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, you can use your debit card. Your PIN is not required because this is a PIN-less debit transaction.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseTen_PQ">Q. Can I use a credit card to make a one-time online payment? </a> </div>
                        <div id="collapseTen_PQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, you can use your Visa or MasterCard credit card to make a payment.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="FQ">
            <div class="accordion" id="Div3">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne_FQ">Q. Forms Question Stub for Later? </a> </div>
                        <div id="collapseOne_FQ" class="accordion-body collapse">
                        <div class="accordion-inner">A. Answer stub for later.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="CQ">
            <div class="accordion" id="Div5">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne_CQ">Q. Claims Question Stub for Later? </a> </div>
                        <div id="collapseOne_CQ" class="accordion-body collapse in">
                        <div class="accordion-inner">A. Answer stub for later.  </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

Javascript Below:

$(document).ready(function () {
$('.modal').appendTo($("body"));

$('#tabFAQ a').click(function (e) {
    e.preventDefault();
    $(this).tab('show');
})

$('.expandcollapse').click(function () {

    $('.collapse').each(function(index) {
        $(this).collapse("toggle");
    });

    if ($(this).html() == "<i class=\"icon-white icon-plus-sign\"></i> Expand All") {
        $(this).html("<i class=\"icon-white icon-minus-sign\"></i> Collapse All");
    }
    else {
        $(this).html("<i class=\"icon-white icon-plus-sign\"></i> Expand All");
    };
});

});

I was wondering if it was because the other tab content wasn't loaded in the DOM when the page is initially loaded. So I used the jquery .each() function hoping they would toggle even if they weren't loaded initially.

Can someone help me detect why the button stops working when tabs get selected?

like image 901
Jon Harding Avatar asked Dec 15 '22 16:12

Jon Harding


1 Answers

There are two problems:

1) Bootstrap uses scrollHeight to transition the height of the .collapse divs but scrollHeight is always 0 when an element is not displayed; when your Expand All button is clicked, the heights of the .collapse divs in the hidden tabs cannot be set properly.

2) The ontransitionend event does not fire on elements which are not displayed. Bootstrap sets a flag (transitioning) in its collapse method which is reset in ontransitionend, however ontransitionend is never fired for the undisplayed elements. Once your Expand All button is clicked, Bootstrap thinks all the undisplayed .collapse divs are in transition and each subsequent call to the collapse method of these divs is short-circuited.

Since you have no control over either of those problems, what needs to be done is to only collapse the divs of the active tab when your Expand/Collapse All button is clicked and to update the collapse setting of the divs in a tab when it becomes active.

I put that together into an update of your jsfiddle.

Updated HTML:

    <ul class="nav nav-tabs" id="tabFAQ">
        <li class="active"><a href="#GQ" data-toggle="tab" state="0">General Questions</a></li>
        <li><a href="#ICQ" data-toggle="tab" state="0">Insurance Coverage</a></li>
        <li><a href="#PQ" data-toggle="tab" state="0">Payment</a></li>
        <li><a href="#FQ" data-toggle="tab" state="0">Forms</a></li>
        <li><a href="#CQ" data-toggle="tab" state="0">Claims</a></li>
    </ul>
    <div class="tab-content" id="faqContent">
        <div class="tab-pane active" id="GQ">
            <div class="accordion" id="generalQuestions">
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseOne">Q. What do I do if I’m having trouble logging in?</a>
                    </div>
                    <div id="collapseOne" class="accordion-body collapse">
                        <div class="accordion-inner">A. Please contact our Customer Care team at 800-821-7303 for assistance.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseTwo">Q. Will additional online services be added to this portal?</a>
                    </div>
                    <div id="collapseTwo" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes. We will be adding many online services to this portal over the next six months.  Please check back often.</div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseThree">Q. What information am I able to access on this portal?</a>
                    </div>
                    <div id="collapseThree" class="accordion-body collapse">
                        <div class="accordion-inner">A. We currently have the ability to display any premiums that are currently due and allow you to make an immediate one-time payment from your checking account, savings account, Visa or MasterCard.  Your payment will be confirmed immediately.  Other functions are planned to be added to the portal over the next six months.  Check back often.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseFour">Q. Can I choose my own Username and Password?</a>
                    </div>
                    <div id="collapseFour" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, you can choose your own Username and Password.  We suggest using your email address for your Username, but any username that is between 8 and 20 characters long could be used.  A secure Password should be 8 to 20 characters long, with no spaces, and contains at least one special character.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading">
                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#generalQuestions" href="#collapseFive">Q. Can I update by email address online?</a>
                    </div>
                    <div id="collapseFive" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, but I have no idea how right now.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="ICQ">
            <div class="accordion" id="Div1">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">Q. Insurance Coverage question Stub for Later? </a> </div>
                        <div id="Div2" class="accordion-body collapse">
                        <div class="accordion-inner">A. Answer stub for later.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="PQ">
            <div class="accordion" id="accordion3">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseSix">Q. When is my payment actually made to my account? </a> </div>
                        <div id="collapseSix" class="accordion-body collapse">
                        <div class="accordion-inner">A. Your payment is posted to your account within 24 hours after receipt of the funds.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseSeven">Q. What is a one-time payment? </a> </div>
                        <div id="collapseSeven" class="accordion-body collapse">
                        <div class="accordion-inner">A. This is a web-based service that enables our customers to make a single payment to pay their insurance premium.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseEight">Q. How do I know my payments are secure? </a> </div>
                        <div id="collapseEight" class="accordion-body collapse">
                        <div class="accordion-inner">A. Our portal uses encryption software and hardware to protect your information. For more information, view our <a href="#">Privacy Policy</a>. </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseNine">Q. Can I use a debit card to make a one-time online payment? </a> </div>
                        <div id="collapseNine" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, you can use your debit card. Your PIN is not required because this is a PIN-less debit transaction.  </div>
                    </div>
                </div>
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion3" href="#collapseTen">Q. Can I use a credit card to make a one-time online payment? </a> </div>
                        <div id="collapseTen" class="accordion-body collapse">
                        <div class="accordion-inner">A. Yes, you can use your Visa or MasterCard credit card to make a payment.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="FQ">
            <div class="accordion" id="Div3">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">Q. Forms Question Stub for Later? </a> </div>
                        <div id="Div4" class="accordion-body collapse">
                        <div class="accordion-inner">A. Answer stub for later.  </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane" id="CQ">
            <div class="accordion" id="Div5">
                <div class="accordion-group">
                    <div class="accordion-heading"> <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">Q. Claims Question Stub for Later? </a> </div>
                        <div id="Div6" class="accordion-body collapse">
                        <div class="accordion-inner">A. Answer stub for later.  </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

Updated JavaScript:

$('.expandcollapse').click(function() {

    var newstate = $(this).attr('state') ^ 1,
        icon = newstate ? "minus" : "plus",
        text = newstate ? "Collapse" : "Expand";

    $('.nav-tabs').children().each(function(index) {
        if($(this).hasClass('active')) {
            var tab = $(this).children(':first');
            toggleTab(tab.prop('hash'));
            tab.attr('state',newstate);
        }
    });

    $(this).html("<i class=\"icon-white icon-" + icon + "-sign\"></i> " + text +" All");

    $(this).attr('state',newstate)

});

$('a[data-toggle="tab"]').on('shown', function (e) {

    var myState = $(this).attr('state'),
        state = $('.expandcollapse').attr('state');

    if(myState != state) {
      toggleTab($(this).prop('hash'));
      $(this).attr('state',state);
    }

})

function toggleTab(id){

    $(id).find('.collapse').each(function() {
        $(this).collapse('toggle');
      });

}
like image 98
ic3b3rg Avatar answered Feb 15 '23 22:02

ic3b3rg