I've got quite a complex search which utilises multiple ajax calls, the flow is as follows:
user performs search on button click
ajax request is made to php page which returns json data
for each result in returned data additional ajax request is made
run function which makes additional ajax call
end for each
end click function
this all works nicely, what i would like to do is display a loading message in a div and disable the search button, then when all the ajax requests have completed re-enable the button and remove the loading message.
my script is below, at the moment the disable/renable of the bu开发者_高级运维tton is happening almost instantaneously, i presume because the ajax calls are asyncronus, how do i go about renabling the button and removing the loading message once all the ajax requests have completed and displayed the data??
$('#advKeyBtn').live('click', function() {
$('#advKeyBtn').attr('disabled', 'disabled');
$('#searchStatus').html('<img src="../img/icons/loadinfo.gif" width="16" height="16" /> Searching Locations...');
$('#results').html(''); //clear existing contents
$('#borough_links').html(''); //clear existing contents
// handler for advance search button
var myUrl = 'getKeyBoroughs.php';
var myKeys = $('#keywords').val();
var myType = $('input[name=keyParams]:checked').val()
$.ajax({
url: myUrl,
data: "keys=" + myKeys +'&type='+myType,
type: "POST",
traditional: false,
dataType: 'json',
error: function(xhr, statusText, errorThrown){
// Work out what the error was and display the appropriate message
},
success: function(myData){
// data retrived ok
$.each(myData.boroughs, function( intIndex, objValue ){
//alert(myData.boroughs[intIndex].Borough_ID);
makeCSS(myData.boroughs[intIndex].Borough_ID);
getKeyLocations(myData.boroughs[intIndex].Borough_ID)
})
//$('#'+divId).append(myData)//construct location holders
}
});
$('#advKeyBtn').attr('disabled', '');
$('#searchStatus').html('Search Complete, click on an area to view locations');
});
and the function that gets called from the initial success of the main ajax call
function getKeyLocations(id){
var myUrl = 'getKeyLocations.php';
var myBorough = id;
var myKeys = $('#keywords').val();
var myType = $('input[name=keyParams]:checked').val()
var divId = '#borough_'+ id;
$.ajax({
url: myUrl,
type: 'POST',
data: 'borough_id='+myBorough+'&keys='+myKeys,
error: function(xhr, statusText, errorThrown){
// Work out what the error was and display the appropriate message
},
success: function(myData){
$(divId).html(myData);
}
});
};
You have to create a function that will handle all your requests. When all requests are finished then enable the button and show the message.
var ajaxLoading = {
_requestsInProcess: 0,
show: function () {
if (this._requestsInProcess == 0) {
$('#advKeyBtn').attr('disabled', 'disabled');
$('#searchStatus').html('<img src="../img/icons/loadinfo.gif" width="16" height="16" /> Searching Locations...');
}
this._requestsInProcess++;
},
hide: function () {
this._requestsInProcess--;
if (this._requestsInProcess == 0) {
$('#advKeyBtn').attr('disabled', '');
$('#searchStatus').html('Search Complete, click on an area to view locations');
}
}
};
now, before all ajax call use:
ajaxLoading.show()
And in all your success methods use:
ajaxLoading.hide()
Hope this helps.
You want ajaxStart and ajaxStop, here is some code to display a loading screen. Such a nice little one liner.
$('.loadingElement')
.ajaxStart(function() { this.show(); })
.ajaxStop(function() { this.hide(); });
For your specific usage, it looks like the code would be something like
$('#advKeyBtn')
.ajaxStart(function() { this.attr('disabled', 'disabled'); })
.ajaxStop(function() { this.attr('disabled', ''); });
jquery: ajaxStart
Whenever an Ajax request is about to be sent, jQuery checks whether there are any other outstanding Ajax requests. If none are in progress, jQuery triggers the ajaxStart event. Any and all handlers that have been registered with the .ajaxStart() method are executed at this time.
jquery: ajaxStop
Whenever an Ajax request completes, jQuery checks whether there are any other outstanding Ajax requests. If none remain, jQuery triggers the ajaxStop event. Any and all handlers that have been registered with the .ajaxStop() method are executed at this time. The ajaxStop event is also triggered if the last outstanding Ajax request is cancelled by returning false within the beforeSend callback function.
from malsup, regarding the differences between ajaxStop and ajaxComplete:
ajaxStop is triggered when the number of outstanding ajax requests reaches zero. ajaxComplete is triggered after each response is received. ajaxComplete is also passed the XHR and the settings object.
Yes, AJAX request are asynchronous. One solution is to make a counter initialized to the number of ajax requests that were sent, and then on each response, decrease the counter. When you reach 0, update your status and reenable. Just keep in mind that you may want to automatically reenable after some timeout in case the network hangs.
Agree with above, buy my suggestion would be to decrement the counter on a timeout or failed response instead of using a timer.
The counter would then be counting the number of responses that were completed (failure or not.)
精彩评论