load doesn't trigger ajaxSetup complete handler on complete - ajax

I have
// Ajax setup
$.ajaxSetup({
beforeSend: function() {
$('#general-ajax-load ').fadeIn();
},
complete: function() {
$('#general-ajax-load ').fadeOut();
}
});
on page load to set loading animation for all my ajax calls. It works perfect, except for load() calls. For loads only beforeSend is triggered, and complete never gets called, Which results with showing animation which never dissapears.
Any idea?

According to http://bugs.jquery.com/ticket/4086#comment:4, the "correct" way would be:
$(document).ajaxSend(function(event, jqXHR, settings) {
$('#general-ajax-load ').fadeIn();
});
$(document).ajaxComplete(function(event, jqXHR, settings) {
$('#general-ajax-load ').fadeOut();
});
I just did some testing and that indeed seems to work in all cases (including $.load).

Adding success fixed the problem, thanks (I can swear I tried it before)
$.ajaxSetup({
beforeSend: function() {
$('#general-ajax-load ').fadeIn();
},
complete: function() {
$('#general-ajax-load ').fadeOut();
}
success: function() {
$('#general-ajax-load ').fadeOut();
}
});
:)

The $.load manual says:
...It is roughly equivalent to
$.get(url, data, success) except that
it is a method rather than global function and it has an implicit
callback function.
It would seem that $.load's implicit callback function is overriding the complete callback in your $.ajaxSetup. The $.ajaxSetup documentation says:
All subsequent Ajax calls using any
function will use the new settings,
unless overridden by the individual
calls, until the next invocation of
$.ajaxSetup().
I guess the solution would be to replace your $.load calls with $.get (or the more verbose $.ajax). You could also try using success instead.

Related

Preventing Ajax save data two times

Whenever I run Ajax in jquery, it will run two times. It will cause a problem in saving data. I googled and used their metods but none of them worked. The following is the ways I tried:
Set a global flag. Set it on when Ajax is running, turn it off after done. It seems that duplicated calls manage the flag concurrently. Before call 1 closed the door, call 2 is already in in no time. Or check time if less than 4000, do not run Ajax.
Generating a random number and attach to the url, they are the same always.
event.preventPropgador();e.preventDefault(); does not work in whichever order
async:true or false does not work
I cannot use "once" since I am usimg jQuery Mobile
$("#submitButton").once("tap", function () { //<-- error
save();
});
used "one" but not work
$("#submitButton").one("tap", function () {
save();
});
disable the button when ajax running, then enable it afterwords.
I tried above techs on save() and Ajax calls, none of them worked.
This is my code like:
$(document).bind("pageinit", function () {
$("#submitButton").one("tap", function () {
save();
});
}
function save() {
$.ajax({method: "get",
url: baseUrl + "save?model=abcd&rand=" + randonNum(),
contentType: "application/json; charset=utf-8",
success: function (response) {
//do whatever
}
},
error: function (request, status, error, errorThrown) {
}
});
}

How to stop AJAX calls if there's an error on a field with a keyup trigger

I have this jquery ajax call that is trigger on keyup. It has error handling which (with Firefox for e.g.) is triggered multiples times if the user enters keystrokes fast. Is there a quick way to stop multiple alert windows to be shown?
$('input[name$="_LOC"]').keyup(function(){
if ($(this).val().length >=4){
$.ajax({
type: 'POST',
url: 'red.asp?q='+$(this).val(),
beforeSend: function() {
[...]
},
success: function(data) {
[...]
},
error: function() {
alert("Oops!")
}
});
}
});
Restart a timer each time the onkeyup is triggered, this means the event only happens when the user has finished typing (or, at least, paused for a second or whatever).
Use timer = setTimeout(yourFunction, yourDelay);
To rest the timer user clearInterval(timer) and start the setTimeout again.
var typing = false;
var timer;
$('input[name$="_LOC"]').keyup(function(){
if(typing) {
clearInterval(timer);
}
timer = setTimeout(sendAjax, 500, [this]);
typing=true;
});
function sendAjax(element)
{
if ($(element).val().length >=4){
$.ajax({
type: 'POST',
url: 'red.asp?q='+$(element).val(),
beforeSend: function() {
[...]
},
success: function(data) {
[...]
},
error: function() {
alert("Oops!")
}
});
typing = false;
}
Here's JSFiddle example: http://jsfiddle.net/X8US5/, you'll need your browsers console.log viewer ready to see stuff (otherwise edit the console.logs to be alerts though they interrupt JS so times will be off)
Edit:
IE9 compatible (hack) version http://jsfiddle.net/5ndM5/1/
Tried to find a jQuery alternative but none it seems.
THe overriding the function alternative is good if you don't want the global var, but if you only plan to use this code on one form then the global is acceptable (JS code is usually rife with them by accident anyway)

what will happen if i call ajax function recursively? it may cause any issues.

<script>
$(document).ready(function(){
ajaxcall();
});
function ajaxcall(){
$.ajax({
url: 'test.php',
success: function(data) {
data = data.split(':');
$('#hours').html(data[0]);
$('#minutes').html(data[1]);
$('#seconds').html(data[2]);
ajaxcall();
}
});
}
</script>
<span id="hours">0</span>:<span id="minutes">0</span>:<span id="seconds">0</span>
In this code i called the ajax function onsuccess, so it will be infinite loop. It cause any problems?
This will cause your browser to run out of memory eventually and crash because each call will be saved on the call-stack. I was wrong; the callback is asynchronous and so control will leave the parent function. If you're trying to update the time, I recommend doing something like this instead:
$(document).ready(function(){
setInterval(ajaxcall, 1000); //calls ajaxcall every 1000 microseconds
});
function ajaxcall(){
$.ajax({
url: 'test.php',
success: function(data) {
data = data.split(':');
$('#hours').html(data[0]);
$('#minutes').html(data[1]);
$('#seconds').html(data[2]);
}
});
}
Nothing bad is going to happen. It'll make the ajax call, wait for it to return, then make another forever. There is nothing wrong with that itself. Just be careful that your server-side operation is not too heavy, and that you're not transferring too much data not to waste too much bandwidth.
If you ever want to be able to stop it, you could make a variable to define whether to keep doing the calls, and just turn it off whenever.
var keepCalling = true;
function ajaxCall() {
if (!keepCalling)
return;
//ajax call...
}
Setting keepCalling to false will stop the calls after the current one is complete.

jQuery - AJAX request using both native XHR and flXHR (Flash) fallback - how to minimize code duplication?

I need to retrieve data via cross-domain XMLHttpRequest. To make this work in (almost) all browsers, I use native XHR first and, if that fails, flXHR.
The (working) code I currently have for this is as follows:
jQuery.support.cors = true; // must set this for IE to work
$.ajax({
url: 'http://site.com/dataToGet',
transport : 'xhr',
success: function(data) {
console.log('Got data via XHR');
doStuff(data);
},
error: function(xhr, textStatus, error) {
console.log('Error in xhr:', error.message);
console.log('Trying flXHR...');
$.ajax({
url: 'http://site.com/dataToGet',
transport : 'flXHRproxy',
success: function (data) {
console.log('Got data via flXHR');
doStuff(data);
},
error: function (xhr, textStatus, error) {
console.log('Error in flXHR:', error.message);
console.log('Both methods failed, data not retrieved.');
}
});
}
});
This feels like a lot of code duplication to me, especially in the success handlers. Is there a more efficient way to do this? I'd really prefer to make one $.ajax call that would try both transports in turn, instead of having to use the error handler to make the call a second time. It's not too bad in this example, but rapidly gets more complicated if the success handler is longer or if the success handler has to itself issue another $.ajax call.
I've created a jquery-specific and slimmed-down fork of flxhr that simplifies your code sample above. You can see an example of usage in the "Usage" section in the README.
https://github.com/b9chris/flxhr-jquery-packed
In particular, you don't want to waste time waiting for a standard CORS request to fail. It's easy to determine whether flxhr is necessary by testing $.support.cors upfront (no need to override it). Then just use flxhr explicitly where necessary.
Why don't you just wrap this in a function by itself? That's after all, how you end up reusing code. You can even pass functions as arguments to make sure that you don't have to repeat this code more than once.
To me this is pretty straight forward but maybe I've misunderstood.
function xhr(success) {
$.ajax({
success: success,
error: function() {
$.ajax({ success: success })
}
});
}
Then just pass the success handler once
xhr(function(data){/*magic*/});
Or if you wanna basically avoid redundant configuration of the ajax call use the first object as a template, like this:
function xhr(success) {
var ajaxParams = { success: success };
ajaxParams.error = function() {
$.ajax($.extend(ajaxParams, { transport: 'xhr' }));
}
$.ajax(ajaxParams);
}
I simplified the whole thing a bit, but I hope you get the point.
Edit
Reading that last bit, maybe this will give you some ideas... it's a variation of that last snippet.
function xhr(success) {
var ajaxParams = { success: success };
ajaxParams.error = function() {
var newParams = $.extend(ajaxParams, { transport: 'xhr' });
newParams.success = function() {
// do something
// arguments is a special array, even if no parameters were
// defined in any arguments where passed they will be found
// in the order they were passed in the arguments array
// this makes it possible to forward the call to another
// function
success.apply(this, arguments);
}
$.ajax(newParams);
}
$.ajax(ajaxParams);
}

Adding JQuery to content loaded with AJAX

I just learned that you can use live() instead of bind() to make sure an event handler still exists after content is reloaded with AJAX... but what can I do with other added JQuery, such as .sortable()? I have a UL that I need to reload after sorting or adding; but after the AJAX reload, the sorting doesn't quite work right...
It doesn't completely lose the sortability, but the dragging become much more difficult; it will jump around and seemingly switch 2 other sections that's not the one I'm trying to drag. This only happens after the partial reload; my guess is that when it reloads, I need to re-attach the sortable... how can I do this? Here's my code:
$("#sections").sortable({
start: function (event, ui) {
startIndex = ui.item.index();
},
update: function (event, ui) {
$.ajax({
type: "POST",
url: "/Form/sortSections",
data: {
formID: '#(Model.formID)',
displayOrder: ui.item.index() + 1,
sectionID: $(ui.item).attr("id"),
startDisplayOrder: startIndex + 1
},
success: function (result) {
$.get("/Form/_AllSections/#(Model.formID)", function (data) {
$("#sections").html(data);
});
},
error: function (req, status, error) {
alert(error);
}
});
}
});
Use the load event with live() so that it runs every time the element is added to the DOM.
http://api.jquery.com/load-event

Resources