views:

242

answers:

2

I'm trying to have a button that onclick will apply a class loading (sets cursor to "wait") to the body, before making a series of ajax requests.

Code is:

$('#addSelected').click(function(){
    $('body').addClass('loading');

    var products = $(':checkbox[id^=add_]:checked');
    products.each(function(){
        var prodID = $(this).attr('id').replace('add_', '');
        var qty = $('#qty_' + prodID).val();
        if($('#prep_' + prodID).val())
        {
            prodID += ':' + $('#prep_' + prodID).val();
        }
        // Have to use .ajax rather than .get so we can use async:false, otherwise
        // product adds happen in parallel, causing data to be lost. 
        $.ajax({
            url: '<?=base_url()?>basket/update/' + prodID + '/' + qty,
            async: false,
            beforeSend: function(){
                $('body').addClass('loading');
            }
        });
    });
});

I've tried doing

$('body').addClass('loading');

both before the requests, and as a beforeSend callback, but there is no difference.

In firebug I can see that body doesn't get the loading class until after the requests are complete.

Any ideas?


I've not got this sorted in a way I consider to be clean, but I have found a solution.

If I add setTimeout(function(){ above var products..., and }, 1); below the end of the products.each block, that chunk gets delayed, so addClass happens first.

+1  A: 

Take a look at the .ajaxStart jquery event.

It would look something like this

$('#addSelected').ajaxStart(function() {
  $('body').addClass('loading');
});

EDIT: I took a look at the jquery documentation and found that setting async = false locks the browser from other actions. From the jquery documentation:

asyncBoolean Default: true

By default, all requests are sent asynchronous (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

Might this be causing the issue? Try logging to the console in the ajaxStart event and see if it is firing.

Jon
Thats also starting after the requests have completed :S
Josh
Logging to the console works fine, its just the jquery method that gets delayed. Looks like I'm going to have to use the setTimeout method.
Josh
A: 

What version of jQuery are you using? I am doing very similar functionality and my calls always take place before the ajax call. I'm using v1.4.2 of jQuery, so maybe your problem is an older version?

Also, because of the fact that you are doing an "each()" loop, you definitely need to call the addClass before the .ajax call.

Charles Boyung
Using 1.3.2, and just tried it with the google hosted 1.4.2, and i'm having the same problem. Theres no other jquery on the page either.
Josh