DavidScherer
DavidScherer

Reputation: 884

Determing collapse state of Bootstrap Collapse-able element

I display an alert for a user until the density of a shipment goes above a certain value. When the page loads, a function runs that handles all these calculations (in case the user is loading something and not starting from scratch) and if the density is less than X the collapse is shown, otherwise it's hidden.

The problem is that when calling .collapse('hide') or .collapse('show') on an element that's already hidden/shown causes it to do the opposite.

I define my alert as such:

<div class="row spacer-bottom collapse in" id="cubicCapacityWarn">

    <div class="span8 offset1">

        <div class="alert alert-error">
            <h4><strong>Cubic Capacity Warning!</strong></h4>
            Shipment Total PCF less than 6, you may be assessed Cubic Capacity surcharges!
        </div>

    </div>

</div>

The jQuery that handles all this:

function updateTotals() {

    var total_weight, total_volume, total_density;

    total_weight = 0;
    total_volume = 0;
    total_density = 0;

    $('#units').find('table.unit').each(function(index){

        var weight, volume, density;

        weight = 0;
        volume = 0;
        density = 0;

        volume = parseFloat($(this).find('.unit_cube').text(), 10);

        $(this).find('tbody.products tr').each(function(pIndex){

            weight += parseFloat($(this).find('.weight').text(), 10);

        });

        density = weight / volume;
        density = density.toFixed(2);

        $(this).find('.unit_density').text(density);

        total_weight += (weight * parseInt($(this).find('.unit_num_of').text(), 10));
        total_volume += (volume * parseInt($(this).find('.unit_num_of').text(), 10));

    });


    total_density = total_weight / total_volume;

    $('#total_weight').text(total_weight.toFixed(2));
    $('#total_volume').text(total_volume.toFixed(2));
    if(isNaN(total_density.toFixed(2))) {
        $('#total_density').text("0.00").trigger('change');
    } else {
        $('#total_density').text(total_density.toFixed(2)).trigger('change');
    }

}

$('#cubicCapacityWarn').collapse({toggle: false})

$('#cubicCapacityWarn').on('shown', function(event){
    event.stopPropagation();
    return false;
});

$('#cubicCapacityWarn').on('hidden', function(event){
    alert('hidden')
    event.stopPropagation();
    return false;
});

$('#total_density').change(function(){

    if(parseFloat($(this).text()) < 6) {

        $('#cubicCapacityWarn').collapse('show');
        alert('show')

    } else {

        $('#cubicCapacityWarn').collapse('hide');

    }

});

updateTotals();

I was thinking to solve this by testing if it's already collapsed before calling .collapse('show'|'hide') but I don't know how. If there's a more elegant solution to this problem, I'd love to hear it.

Also, I found this issue If the first call to collapse is hide the collapsable will show instead here which seems related but I added the $('#...').collapse({toggle: false}); with no effect.

Upvotes: 4

Views: 17718

Answers (4)

Juraj B&#233;ger
Juraj B&#233;ger

Reputation: 135

I know this is an older post, but I've been stuck on this one too. So with bootstrap 4.1 I use this to examine the state of the accordion:

var isVisible = $('#collapseOne').is( ":visible" );
alert(isVisible);

and the other way arround, if You want to check if it is hidden:

var isHidden = $('#collapseOne').is( ":hidden" );
alert(isHidden);

Upvotes: 10

tofirius
tofirius

Reputation: 173

Another option: Check if it is missing the .in class.

if(!$('#collapseTwo').hasClass('collapse in')){
   $('#collapseTwo').collapse('show');
}

Upvotes: 1

GGleGrand
GGleGrand

Reputation: 1650

I use this, for example, to determine if element collapseTwo is closed, and then to open it. Works the other way around too, of course.

if ($('#collapseTwo').attr('aria-expanded') == "false") {$('#collapseTwo').collapse('show');}

Upvotes: 6

DavidScherer
DavidScherer

Reputation: 884

The following seems to be working, though I'd love to see a better answer or solution, what I'm doing feels hacky and would probably make most jQ devs cringe.

Basically, I now show/hide the alert from within the updateTotals() function. I changed from using the show/hide events that happen after the collapse and am now using those events that fire before the collapse happens. I test to see if the height of the collapse is what I would expect it to be for what I'm about to do (if I'm about the show it but the height is > 0 it must already be shown) and if it fails this sanity check I return false which seems to be canceling the event from firing (I hope) or something similar because currently, unless there's a case I'm not testing for, this works as it should. Attempting to show the alert when it's shown does not hide it and vice versa.

function updateTotals() {

    var total_weight, total_volume, total_density;

    total_weight = 0;
    total_volume = 0;
    total_density = 0;

    $('#units').find('table.unit').each(function(index){

        var weight, volume, density;

        weight = 0;
        volume = 0;
        density = 0;

        volume = parseFloat($(this).find('.unit_cube').text(), 10);

        $(this).find('tbody.products tr').each(function(pIndex){

            weight += parseFloat($(this).find('.weight').text(), 10);

        });

        density = weight / volume;
        density = density.toFixed(2);

        $(this).find('.unit_density').text(density);

        total_weight += (weight * parseInt($(this).find('.unit_num_of').text(), 10));
        total_volume += (volume * parseInt($(this).find('.unit_num_of').text(), 10));

    });


    total_density = total_weight / total_volume;

    $('#total_weight').text(total_weight.toFixed(2));
    $('#total_volume').text(total_volume.toFixed(2));
    if(isNaN(total_density.toFixed(2))) {
        $('#total_density').text("0.00").trigger('change');
    } else {
        $('#total_density').text(total_density.toFixed(2)).trigger('change');
    }

    if((total_density.toFixed(2) < 6) || isNaN(total_density.toFixed(2))) {
        $('#cubicCapacityWarn').collapse('show');
    } else {
        $('#cubicCapacityWarn').collapse('hide');
    }

}

$('#cubicCapacityWarn').collapse({toggle: false})

$('#cubicCapacityWarn').on('show', function(event){

    if($(this).height() > 0) {
        return false;
    }

    console.log('shown');
    event.stopPropagation();

});

$('#cubicCapacityWarn').on('hide', function(event){

    if($(this).height() == 0) {
        return false;
    }

    console.log('hidden');
    event.stopPropagation();
});

Upvotes: 0

Related Questions