3

I don't have the jQuery/Javascript knowledge to solve this one; it has something to do with events and the order in which the DOM gets manipulated.

Expresso Store provides dynamic classes to let you output stock level info for a product's variants dynamically (as the user selects different combinations using the modifier <select> menus). So if you have a hat product and it has modifiers called Size and Color, you can show the user that Large Red and Medium Green hats are out of stock, but there are 5 Medium Red hats available. That is, assuming you've set stock levels for every SKU, you can insert this into your template:

<p>Stock Level for this variant: <span class="store_product_stock"></span></p>
<p class="store_product_out_of_stock">Sorry, that variant is out of stock.</p>

The contents of the span in the first paragraph will update dynamically with a number, and the second paragraph will only be shown if the stock level for the variant is 0. This works even on page load: that is, Store's javascript assesses the stock of the "default" variant and manipulates both paragraphs above appropriately.

Here's the thing: for out-of-stock variants, I'd like to not only insert the "out of stock" message but also disable the add-to-cart button, so users can't attempt to add them (which would confusingly take them to an empty cart page).

So it seems a shortcut would be to check the visibility of the "out of stock" message, then apply the disabled attribute to the add-to-cart button:

function check_stock() {
    if($('.store_product_out_of_stock').is(':visible')) {
        $('#add-to-bag').attr('disabled','disabled');
    }

    else {
        $('#add-to-bag').removeAttr('disabled');
    }
}

And I'd better run that both on page load and on modifier changes:

$(document).ready(function() {
     check_stock();

    $(".controls select").change(function() {
        check_stock();
    });
}); // end doc read

The problem is, this only works when the modifier <select> menus are changed; it doesn't work on page load.

Despite being inside $(document).ready(), my check_stock() sees the .store_product_out_of_stock element as visible even when Store's javascript is hiding it. Once the user starts changing modifier selects, everything works perfectly, but I really need it to work on page load.

So I then tried checking the numeric value of the variant's stock level:

function check_stock() {

    var variant_stock =  ($('.store_product_stock_level').text());

    if ( (variant_stock != '') && +variant_stock < 1 ) {
        $('#add-to-bag').attr('disabled','disabled');
    }
    else {
        $('#add-to-bag').removeAttr('disabled');
    }
    console.log("variant stock is " + variant_stock);
    console.log("numberized stock is " + (+variant_stock));
}

But this has the same problem: the console shows that, on page load, jQuery is only getting an empty string for variant_stock, even though right there on the page (and in the web inspector) I can see Store has correctly inserted the stock level.

Is there some way, on page load, to make my jQuery wait for Store's javascript to manipulate the DOM before swooping in and checking the stock situation?

4

Instead of handling the page ready event, or when your select menus changing, you can set your function to run when the stock level changes.

Create a (hidden if necessary) stock level indicator like this:

<span class="store_product_stock_level"></span>

Then handle its change event:

$(function() {
    $('.store_product_stock_level').change(function() {
        if ($(this).text() == '0') {
            $('#add-to-bag').attr('disabled', true);
        } else {
            $('#add-to-bag').attr('disabled', false);
        }
    });
});

Note that the store_product_stock_level dynamic variable was called store_product_stock prior to Store 2.0.4 (and store_product_stock is still available for backwards compatibility).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.