views:

88

answers:

3

Hi I have a huge problem that's been bugging me for quite a while, most of the times I have been able to avoid it but now there is no other way. Below is a function that when executed sends a post request for every checked boxes. I need it to wait until the $.each has finished to refresh the page. I have performed tests with location.reload in the callback of each and outside of each. Out of 10 selected boxes only 7-8 are processed with the reload in the callback of $.each and 3-4 if moved after $.each (still inside the .click). I need it to wait, somehow, for $.each to finish and then refresh the page. Is there a way to do that?

$('button.moveToTable').click(function(event){
            $("input:checked").each(function(){
                $.post('/table/move-to-table',
                {orderID: $(this).val(),
                    tableID: $('#moveToTableID').val()
                },
                function(data){
                    location.reload();
                });
            });
            //location.reload();
        });
+2  A: 

One simple way is to store the number of elements in a global scope and subtract them. When the last element finishes the request it will reload. Note that if some request return an error this will fail, you have to handle the error event as well subtracting the window.Remaining. Two or more clicks might corrupt this method as well.

window.Remaining = 0;
$('button.moveToTable').click(function(event){
    window.Remaining = $("input:checked").length;
    $("input:checked").each(function(){
        $.post('/table/move-to-table',
        {orderID: $(this).val(),
            tableID: $('#moveToTableID').val()
        },
        function(data){
            --window.Remaining;
            if (window.Remaining == 0)
                window.location.reload();
        });
    });
    //location.reload();
});
BrunoLM
Nice idea to use the `length` property. You could probably avoid running the selector twice by doing something like `window.Remaining = $('input:checked').each(function() { ... }).length`. :o)
patrick dw
just a side note: why are you putting this under `window`? This would work just as well in local scope. no need to pollute global namespace.
broady
+3  A: 

Not sure if this is the best solution, but one idea would be to increment a count of the requests sent for each one, then decrement it as the requests return.

Use the count as a flag to determine if the reload() should fire.

Something like this:

var count = 0;

$('button.moveToTable').click(function(event){
            $("input:checked").each(function() { 
                count++; // Increment the counter for each request

                $.post('/table/move-to-table',
                {orderID: $(this).val(),
                    tableID: $('#moveToTableID').val()
                },
                function(data) { 
                    count--; // Decrement as the requests return

                        // Only reload if the count is 0
                    if( count === 0 )
                        location.reload();
                });
            });
        });

You should probably have some code to prevent the click from occurring from a second click. You could probably use the same count variable for that.

As in:

if( count === 0 ) { 
    $("input:checked").each(func...

Or a better idea may be to use this solution from nsw1475 and send only one request for all the checkboxes if that option is available to you.

patrick dw
+2  A: 

A better, more efficient and bug-free way to do this might be to use the each() function to generate a json array storing which checkboxes have been checked, and then use .post to pass all of your data together. After that is done, call page refresh.

nsw1475