I would like to show the "LoaderMain" div before the .load() and when it is all complete hide the "LoaderMain". When I uncomment my show/hide it never displays.
$('#content').html('');
//$('#LoaderMain').show();
$("#content").load(url, function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error: ";
$("#content").html(msg + xhr.status + " " + xhr.statusText);
}
});
//$('#LoaderMain').hide();
Put $('#LoaderMain').hide(); in your callback function.
For example:
$('#content').html('');
$('#LoaderMain').show();
$("#content").load(url, function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error: ";
$("#content").html(msg + xhr.status + " " + xhr.statusText);
}
$('#LoaderMain').hide();
});
Since load is asynchronous, you'll need your hide() function inside the callback:
$('#content').html('');
$('#LoaderMain').show();
$("#content").load(url, function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error: ";
$("#content").html(msg + xhr.status + " " + xhr.statusText);
}
$('#LoaderMain').hide();
});
$("#content").load(url, function(response, status, xhr) {
// Stuff 1
$('#LoaderMain').hide();
});
// Stuff 2
Load is asynchronous, it means that the function Load will start, and while it runs, the script continues to stuff 2, and once the function running in background finshes, it does stuff 1. Note that if the function is very fast, stuff 1 can be done before stuff 2.
If the function was synchronous, stuff 1 would always be done before stuff 2.
That's why AJAX means Asynchronous JavaScript Xml, because it is made to run in background.
$('#content').html('');
//$('#LoaderMain').show();
$.ajax({
url: "your.url",
beforeSend: function() {
//do something before sending the ajax, like hiding or showing that spinner
},
type: 'post', //or get if you prefer that
data: "", // put parameters like ?id=1&name=something here
success: function(data) {
//do something after successful ajax request like $('#content').html(data);
}
});
What event are you using to load content with?
http://api.jquery.com/load/#callback-function
Most jquery event/ajax functions have a callback param that you can send a function to, in order to execute after the event/ajax function has complete processing.
$('#LoaderMain').show();
$('#result').load('ajax/test.html', function() {
$('#LoaderMain').hide();
});
Related
I am trying to make an instant search drop down for my site. All work fine, except for this.
var timeOut;
$('#search input[name=\'search\']').on('keyup', function(e) {
// If enter - submit the search field
if (e.keyCode == 13) {
$('header input[name=\'search\']').parent().find('button').trigger('click');
}
// Call only when length is at least 2 and the key pressed is alphanumeric
else if ($('#search input[name=\'search\']').val().length>2 && ((e.keyCode>=65 && e.keyCode<=90) || (e.keyCode>=97 && e.keyCode<=122))) {
timeOut = null;
//alert(timeOut);
if (!timeOut) {
timeOut = setTimeout(function() {
$.ajax({
url: 'ajax.php',
type: 'post',
async: false,
data: 'ACTION=SEARCH&search='+$('#search input[name=\'search\']').val(),
dataType: 'json',
beforeSend: function() {
$('#loader-icon').show();
},
complete: function() {
$('#loader-icon').hide();
},
success: function(json) {
//$('.product-list-row').html(json);
$('#search-listing').html(json['html']);
},
error: function(xhr, ajaxOptions, thrownError) {
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
timeOut = null;
}, 500);
}
}
});
Problem 1: My script ends up making too many calls to the server, for some reason setTimeOut isn't working as I expected it to. Ajax call should only be made when the user has done typing or something like that and not at every key press.
Problem 2: For some reason when I type fast the input bar doesn't get edited. The ajax however works, but with the last textual input.
Instead of trying to tackle this with setTimeout, you can abort the previous call using the jqXHR object returned by the AJAX. It is more clean and simple to use this. Remove async: false, too.
var timeOut;
var xhr;
$('#search input[name=\'search\']').on('keyup', function(e) {
// If enter - submit the search field
if (e.keyCode == 13) {
$('header input[name=\'search\']').parent().find('button').trigger('click');
}
// Call only when length is at least 2 and the key pressed is alphanumeric
else if ($('#search input[name=\'search\']').val().length>2 && ((e.keyCode>=65 && e.keyCode<=90) || (e.keyCode>=97 && e.keyCode<=122))) {
if(xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: 'ajax.php',
type: 'post',
data: 'ACTION=SEARCH&search='+$('#search input[name=\'search\']').val(),
dataType: 'json',
beforeSend: function() {
$('#loader-icon').show();
},
complete: function() {
$('#loader-icon').hide();
},
success: function(json) {
//$('.product-list-row').html(json);
$('#search-listing').html(json['html']);
},
error: function(xhr, ajaxOptions, thrownError) {
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
});
The right solution is combination of both, abort running request, if new one should be made, and also, tackle firing of the new request. You can use underscore library, which has nice function for that, called debounce (see http://underscorejs.org/#debounce) and your code should looks like this:
// This is your xhr, each request save into this
// variable, in order to be able to abort it if needed
var xhr;
// Wrap your event handler using the debounce function
$("#search").on("keyup", _.debounce(function(e) {
// Abort running request
if(xhr) {
xhr.abort();
xhr = null;
}
// Store the new request
xhr = $.ajax({
// Search for the term $(this).val()
});
},500));
There is no need to fire the search for each keyup, but only when user stopped typing - debounce will do it for you. And there is no need to handle previous results if the request should be made.
I'm having problems with the return value of a jQuery ajax call. I can debug the whole thing server side and I know everything is working correctly and the return value is properly being calculated. I can look under the NET tab in FireBug and see that the response is:
{"d":false}
But when I test the value in the Success function of the ajax call, msg is NULL. Why?
Here's the ajax call:
function GetStateCertifiable(areaID) {
$.ajax({
url: "../WebServices/AoP.asmx/GetStateCertifiable",
data: '{"AreaID":"' + areaID + '"}',
dataType: 'json',
success: function (msg) {
alert(msg); // for debugging
if (msg)
$("#isCertified").slideDown("fast");
else
$("#isCertified").slideUp("fast");
},
error: function (msg) {
alert("An error occured. \nStatus: " + result.status
+ "\nStatus Text: " + result.statusText
+ "\nError Result: " + result);
},
complete: function () {
}
});
};
Other, similarly structured client-side calls work fine. This is a same-domain request.
try changing the name of the variable to something other than msg. I think that might be a message box or something similar. Try
function GetStateCertifiable(areaID) {
$.ajax({
url: "../WebServices/AoP.asmx/GetStateCertifiable",
data: '{"AreaID":"' + areaID + '"}',
dataType: 'json',
success: function (result) {
alert(result); // for debugging
if (result)
$("#isCertified").slideDown("fast");
else
$("#isCertified").slideUp("fast");
},
error: function (result) {
alert("An error occured. \nStatus: " + result.status
+ "\nStatus Text: " + result.statusText
+ "\nError Result: " + result);
},
complete: function () {
}
});
};
It turns out the problem was that my web service (../WebServices/AoP.asmx/GetStateCertifiable) returned a bool and from the post response, I know that was properly sent back to the client. Ajax, however, didn't like that. Once I changed the web service to return the strings "true" or "false", everything worked.
Does jQuery ajax only work for strings or is there something I should have done to prepare the msg object to receive a bool?
I am working ona application, when the user clicks on the "save" button in the application, it saves the information and restarts the server.
The form has to be successfully submitted before ajax success will fire. If the information is saved correctly from the form, i get a 200 success message from the server.
If there is success(200) the server restarts, when the Server restarts or is restarting it gives a 500 internal server message, it take about 30 to 40 sec or more to restart the server so i have await time for 30 sec..
Once the server restarts it gives a 200 success server message.
Currently I am using Ajax call 2 to check for success for data submission for server restart and the other 1st Ajax call 1 to recheck the server is restarting and the data has been updated.
I have currently the following 2 ajax codes
Ajax call 1
$.ajax({
// dataType : 'jsonp',
//jsonp : 'js',
url: "some.json",
beforeSend : function(jqXHR, settings) {
console.info('in beforeSend');
console.log(jqXHR, settings);
},
error : function(jqXHR, textStatus, errorThrown) {
alert(" 500 top data still loading"+ jqXHR + " : " + textStatus + " : " + errorThrown);
console.info('in error');
console.log(jqXHR, textStatus, errorThrown);
},
complete : function(jqXHR, textStatus) {
alert(" complete "+ jqXHR + " : " + textStatus);
console.info('in complete');
console.log(jqXHR, textStatus);
},
success: function(data, textStatus, jqXHR){
alert(" success "+ jqXHR + " : " + textStatus);
console.info('in success');
console.log(data, textStatus, jqXHR);
}
});
Ajax call 2
$(function () {
$("#save").click(function () {
$.ajax({
type: "POST",
url: "some.json",
data: json_data,
contentType: 'application/json',
success: function (data, textStatus, xhr) {
console.log(arguments);
console.log(xhr.status);
alert("Your changes are being submitted: " + textStatus + " : " + xhr.status);
$('#myModal').modal('hide');
/*
This gives a messagthat the server is restarting iina modal window and waits for 30sec
*/
$('#myModal-loading').modal('show');
/*** Re check bit by Ryan ***/
var restartCheck = window.setInterval(
$.ajax({
// dataType : 'jsonp',
//jsonp : 'js',
url: "../../../../../rest/configuration",
beforeSend: function (jqXHR, settings) {
console.info('in beforeSend');
console.log(jqXHR, settings);
},
error: function (jqXHR, textStatus, errorThrown) {
alert(" 500 top data still loading " + jqXHR + " : " + textStatus + " : " + errorThrown);
console.info('in error');
console.log(jqXHR, textStatus, errorThrown);
},
complete: function (jqXHR, textStatus) {
alert(" complete " + jqXHR + " : " + textStatus);
console.info('in complete');
console.log(jqXHR, textStatus);
},
success: function (data, textStatus, jqXHR) {
window.clearInterval(restartCheck);
alert(" success " + jqXHR + " : " + textStatus);
console.info('in success');
console.log(data, textStatus, jqXHR);
}
}), 30000); //This will call the ajax function every 3 seconds until the clearInterval function is called in the success callback.
/*** recheck bit **/
setTimeout(function () {
location.reload(true);
}, 30000);
$('<div id="loading">Loading...</div>').insertBefore('#myform-wiz');
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.responseText + " - " + errorThrown + " : " + jqXHR.status);
}
});
});
});
});
Is it possible to re-check continuously within success in Ajax call 2 , if the server is giving a 500 error message to check for restart of server and recheck for success for 200 before redirecting back to the updated page?
You could probably just use a setInterval. Don't forget to clear it in the success callback.
var restartCheck = window.setInterval(
$.ajax({
// dataType : 'jsonp',
//jsonp : 'js',
url: "some.json",
beforeSend : function(jqXHR, settings) {
console.info('in beforeSend');
console.log(jqXHR, settings);
},
error : function(jqXHR, textStatus, errorThrown) {
alert(" 500 top data still loading"+ jqXHR + " : " + textStatus + " : " + errorThrown);
console.info('in error');
console.log(jqXHR, textStatus, errorThrown);
},
complete : function(jqXHR, textStatus) {
alert(" complete "+ jqXHR + " : " + textStatus);
console.info('in complete');
console.log(jqXHR, textStatus);
},
success: function(data, textStatus, jqXHR){
window.clearInterval(restartCheck);
alert(" success "+ jqXHR + " : " + textStatus);
console.info('in success');
console.log(data, textStatus, jqXHR);
}
})
, 3000); //This will call the ajax function every 3 seconds until the clearInterval function is called in the success callback.
Well, my idea could be to put your ajax request inside a method and do the following:
1. Send the request to save your data and restart server.
2. In the process you need to validate that the data is not repeated in the database.
3. If there is an error present then the method is executed again and again but the data is not double saved due to the validation implemented in number 2 and only the server gets restarted.
To start all this, I made a simulation of your situation. Just to know, I don't know which kind of server language are you using (because it is not specified in the question tags) but I will use PHP for making this easy...
The following example makes this:
A user inputs his/her name inside a textbox and then when he/she clicks the "Save" button, the data will be send to the server and, after 50s the callback will be returned to client side. But, if the input name is oscar then the server will return a 500 HTTP error and you will see how the code gets executed again to try "restarting" the server one more time (remember it's a simulation). Otherwise everything will return a 200 HTTP OK.
Please read all comments inside the code, check the browser console and if you can... test it!
index.php: This is the main page.
<html>
<head>
<title>Simulation</title>
</head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#btn').click(function() {
save();
});
});
function save() {
$('#msg').text('Please wait while restarting the server...').show();
$('#btn').hide();
$.ajax({
type: 'POST',
url: 'process.php',
data: $('form').serialize(),
statusCode: {
500: function() {
console.log('500 HTTP error present, try again...');
/* Invoke your method again to try restarting the server.
* To avoid double save of 'name' variable please
* check the first comments at 'process.php' file.
*/
$('#msg').text('Re-trying to restart the server...');
/* While waiting check the browser console and look that
* the save method is getting invoked again and again until
* you change the name from 'oscar' to another.
*/
save();
},
200: function() {
$('#msg').text('Server restarted!').fadeOut('slow');
$('#btn').fadeIn();
}
}
});
};
</script>
<body>
<span id="msg"></span>
<br/>
<form>
Name: <input type="text" name="name" id="name"/><br/>
<input type="button" name="btn" id="btn" value="Save"/>
</form>
</body>
</html>
process.php: This file will receive the ajax request from jQuery (Just to know I am using version 1.7.2).
<?php
if(isset($_POST['name'])){
$name = $_POST['name'];
/* TODO: In this case and at this point, you need to save the
* name into DB but only if it doesn't exist because if 500 error
* is present, then the request have to be validated again to
* just restart the server (maybe doing some if/else to evaluate) and
* don't make a double save.
*/
/* TODO: restart the server...
* I will simulate the long wait for the server to respond (50s)
* using sleep before sending back the name variable to client side.
*
* But!
* I will do a tricky thing at this point. If the name is 'oscar' then
* I will produce a 500 HTTP error to see what happens at client side...
*/
/* Wait first 27s */
sleep(27);
/* If $name is 'oscar' then return 500 error */
if($name == 'oscar') {
throw new Exception('This is a generated 500 HTTP server error.');
}
/* If $name != 'oscar' then wait 23s to simulate
* the long time for restarting server...
*/
sleep(23);
flush();
/* Retun $name in the callback */
echo $name;
}
?>
Hope this helps :-)
How can I handle errors in AJAX?
In my code, the else condition containing console.log is not executed even when the departments.json file is not loaded. I checked it by deleting the departments.json file from where it is loaded into the code.
My code is:
$.getJSON("departments.json?" + new Date().getTime(), {}, function(departments, status, xhr) {
if (xhr.status == 200) {
var numericDepts = [];
var nonNumericDepts = [];
for(dept in departments) {
$("#kss-spinner").css({'display':'none'});
if (isNaN(departments[dept].depNo)) {
if (isNaN(parseInt(departments[dept].depNo,10)))
nonNumericDepts[nonNumericDepts.length] = departments[dept];
else
numericDepts[numericDepts.length] = departments[dept];
}
else
numericDepts[numericDepts.length] = departments[dept];
}
numericDepts.sort(cmp_dept);
nonNumericDepts.sort(function(dept1,dept2) {
return dept1.depNo.toLowerCase() - dept2.depNo.toLowerCase();
});
departments.sort(cmp_dept);
var k = 0;
$.each(numericDepts.concat(nonNumericDepts), function() {
if (k % 2 == 0) {
$('<p class="odd" onClick="selectTag(this,\'' + this.id + '\', 1)">' + this.depNo + '</p>').appendTo($(".scroller", $("#br1")));
}
else {
$('<p class="even" onClick="selectTag(this,\'' + this.id + '\', 1)">' + this.depNo + '</p>').appendTo($(".scroller", $("#br1")));
}
k++;
});
$("#kss-spinner").css({'display':'none'});
}
else {
console.log(xhr.status);
console.log(xhr.response);
console.log(xhr.responseText)
console.log(xhr.statusText);
console.log('json not loaded');
}
});
You could just use the generic ajax() function:
$.ajax({
url: url,
dataType: 'json',
data: data,
success: successCallback,
error: errorCallback
});
You will need to use the fail() method in order to accomplish that.
Example:
$.get("test.php")
.done(function(){ alert("$.get succeeded"); })
.fail(function(){ alert("$.get failed!"); });
if you need a generic error handler use
$.ajaxSetup({
error: function(xhr, status, error) {
// your handling code goes here
}
});
JQuery's getJSON function is an abstraction over the regular .ajax() method - but it excludes the error callback.
Basically, the function you define is only called if the call is successful (that's why it never gets to the else part).
To handle errors, set an error handler before like this:
$.ajaxError(function(event, jqXHR, ajaxSettings, thrownError) { alert("error");});
Whenever an AJAX request completes with an error, the function will be called.
You can also append the .error at the end of your getJSON call:
$.getJSON("example.json", function() {
(...)
}).error(function() { (...) });
The $.getJSON() function is just a special purpose version of the more general .ajax() function.
.ajax() function will give you the extra functionality you desire (such as an error function). You can read more documentation here http://api.jquery.com/jQuery.ajax/
$.ajax({
url: "departments.json?" + new Date().getTime(),
dataType: 'json',
success: function(departments){
var numericDepts = [];
var nonNumericDepts = [];
for(dept in departments)
{
$("#kss-spinner").css({'display':'none'});
if(isNaN(departments[dept].depNo))
{
if(isNaN(parseInt(departments[dept].depNo,10)))
nonNumericDepts[nonNumericDepts.length]=departments[dept];
else
numericDepts[numericDepts.length]=departments[dept];
}
else
numericDepts[numericDepts.length]=departments[dept];
}
numericDepts.sort(cmp_dept);
nonNumericDepts.sort(function(dept1,dept2) {
return dept1.depNo.toLowerCase() - dept2.depNo.toLowerCase();
});
departments.sort(cmp_dept);
var k=0;
$.each(numericDepts.concat(nonNumericDepts),function(){
if(k%2==0){
$('<p class="odd" onClick="selectTag(this,\''+this.id+'\',1)">'+this.depNo+'</p>').appendTo($(".scroller",$("#br1")));
} else {
$('<p class="even" onClick="selectTag(this,\''+this.id+'\',1)">'+this.depNo+'</p>').appendTo($(".scroller",$("#br1")));
}
k++;
});
$("#kss-spinner").css({'display':'none'});
},
error: function(xhr, textStatus, errorThrown) {
console.log(xhr.status);
console.log(xhr.response);
console.log(xhr.responseText)
console.log(xhr.statusText);
console.log('json not loaded');
}
});
I have a small function (below) that takes a parameter to determine what to load. Is there a way I can make it so that the .load() kind of has an "else" or a fallback if it ecounters a 404?
function start(page,last){
$("#area").load("pages/"+page+".inc.php");
loading();
}
Thanks in advance :)
You can specify a function to be executed when the load completes.
Taken from the documentation:
$("#success").load("/not-here.php", function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error: ";
$("#error").html(msg + xhr.status + " " + xhr.statusText);
}
});
Using your code it would look similar to this:
function start(page,last){
$("#area").load("pages/"+page+".inc.php", function(response, status, xhr) {
if (status == "error") {
// don't load as an error occured,...do something else...
}
else{
loading();
};
});
}
You can check the linked documentation for more details on possible return values and errors. In fact the demo on the bottom of the documentation shows dealing with a 404.
xhr.status in the sample contains the error number 404 and the xhr.statusText is Not Found.
This would mean you can check for the specific number:
function start(page,last){
$("#area").load("pages/"+page+".inc.php", function(response, status, xhr) {
if (status == "error" && xhr.status == ""404) {
// a 404 occurred...
}
else{
loading();
};
});
}
See DEMO
.load() has responseText and textStatus parameters that tell you when it succeeds so you can use that to check if it fails. A successful response will generate "success" or "notmodified" while an error generates "error".
$("#success").load("/not-here.php", function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error: ";
$("#error").html(msg + xhr.status + " " + xhr.statusText);
}
});
in the ajaxSetup you can define the status code like
$.ajaxSetup({
statusCode: {
404: function() {
alert("page not found");
//load the 404 page here
}
}
});