Reputation: 11756
I'm trying to clear a busy icon and re-enable my delete button once the multiple jquery posts have completed. Here is my current code:
$('#deleteimgs').live('click', function(e) {
e.preventDefault();
if ($('input[name="chk[]"]:checked').length > 0 ) {
$('#deleteimgs').button('loading');
$('#saveicon').show();
var boxes = $('input[name="chk[]"]:checked');
$(boxes).each(function(){
var id = $(this).attr('id').substr(7);
var self = this;
$.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
if (data.success) {
$(self).hide();
$("#img_"+id).hide(250);
}
}, "json");
});
$('#saveicon').hide();
$('#deleteimgs').button('reset');
}
});
My hide call and reset call are being trigger prior to completion of the foreach loop. Is there a way to wait for completion before making these two calls?
$('#saveicon').hide();
$('#deleteimgs').button('reset');
Upvotes: 0
Views: 362
Reputation: 51916
To follow up on DwB's answer, using async would be an easy way to supply the intermediary function. instead of:
$(boxes).each(function(){
Use:
async.parallel(boxes.toArray().map(function(elem){
var self = elem;
return function (callback) {
var id = $(self).attr('id').substr(7);
$.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
if (data.success) {
$(self).hide();
$("#img_"+id).hide(250);
callback();
} else {
callback(new Error("request failed"));
}
}, "json");
}
}), function (err) {
if(err) {
console.log(err);
} else {
$('#saveicon').hide();
$('#deleteimgs').button('reset');
}
});
That should work.
Upvotes: 0
Reputation: 318282
Try something like :
$(document).on('click', '#deleteimgs', function(e) {
e.preventDefault();
if ($('input[name="chk[]"]:checked').length > 0 ) {
$('#deleteimgs').button('loading');
$('#saveicon').show();
var boxes = $('input[name="chk[]"]:checked'),
xhr = [];
boxes.each(function(){
var self = this,
id = self.id.substr(7);
var request = $.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
if (data.success) {
$(self).hide();
$("#img_"+id).hide(250);
}
}, "json");
xhr.push(request);
});
$.when.apply(null, xhr).done(function() {
$('#saveicon').hide();
$('#deleteimgs').button('reset');
});
}
});
This will store all the requests in an array that is later passed to $.when, and when they are all done the done()
function will be executed.
Upvotes: 1
Reputation: 38310
You need to count the number of posts you make, call an intermediary function to count the replys, then do the hide and reset after all calls have completed.
for example:
var postCount = 0;
function allPostsDone()
{
$('#saveicon').hide();
$('#deleteimgs').button('reset');
}
postCount += 1;
$.post("/functions/photo_functions.php",
{ f: 'del', imgid: id},
function(data)
{
if (data.success)
{
$(self).hide();
$("#img_"+id).hide(250);
}
postCount -= 1;
if (postCount == 0)
{
allPostsDone();
}
}, "json");
Upvotes: 0
Reputation: 25541
You should use the success
callback method to complete any tasks once the HTTP request has finished. Inside of the callback you should keep track of how many requests have completed, and when your last request has finished, then execute the code of your desire.
You could restructure this code in a few ways, but, it should give you a general idea of how to handle the situation.
var boxes = $('input[name="chk[]"]:checked');
var totalBoxes = boxes.length;
var completedRequests = 0;
$(boxes).each(function(){
var id = $(this).attr('id').substr(7);
var self = this;
$.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
if (data.success) {
$(self).hide();
$("#img_"+id).hide(250);
//Increment the complete request count.
completedRequests++;
//Check if the last request has finished. If it has, do your stuff!
if (completedRequests == totalBoxes) {
$('#saveicon').hide();
$('#deleteimgs').button('reset');
}
}
}, "json");
});
Upvotes: 3