My ajax calls are not causing my .ajaxStop function to be called - javascript

I have the following code
$(document).ready(function () {
$("html")
.ajaxStart(function () {
$(this).addClass("wait");
})
.ajaxStop(function () {
$(this).removeClass("wait");
});
});
$.ajax({
url: url
})
.done(onDone)
.fail(onFail);
When the ajax is executed it goes to the ajaxStart and the class wait is added.
When the ajax is completed it goes to the onDone function but never goes to
the ajaxStop anonymouns function.
Can someone give me some advice on this.

Related

Executing my code during when ajax is in progress

Given my below code Is there a way i can get alert when my ajax process is still in progress?
as you have already noticed code for alert will never get executed because of obvious reason that async ajax will keep happening but the value of click false will come before that and i will never be able to get alert during ajax call. Is there any way i can get alert when ajax request still in process?
<html>
<body>
<button type="button" id="submit-catalog" class="btn btn-primary">Activate</button>
</body>
</html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
var clicked = false;
$(document).on('click', '#submit-catalog', function() {
clicked = true;
//doing some ajax call which is taking time
});
if(clicked){ // never get executed
alert("button clicked")
//i am executing some function only if that button clicked
}
});
</script>
Your logic is off; here's how to do this:
var clicked;
$(document).ready(function() {
$(document).on('click', '#submit-catalog', function() {
if (clicked) {
console.log("ajax still in progress");
return false;
}
clicked = true;
console.log("starting ajax");
setTimeout(function () {
clicked = false;
console.log("ajax done");
}, 3000);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="submit-catalog" class="btn btn-primary">Activate</button>
I'm not sure if this is what you're looking for, but this will prevent the ajax from firing again and again based on the variable which keeps track of the ajax progress.
It's not about Ajax. Code is getting executed top to bottom, you declared event listener on the document and it waits for action, while your 'if' statement was already processed.
This 'Alert' or any other action should be done within event listener
Also, if you want to do any action before executing ajax request you simply use beforeSend: ()=>{/*your actions*/}, and then after ajax request is done success: callback=>{/*do when done*/}
which may look like that:
$.ajax({
url: url,
method: 'POST',
beforeSend: ()=> { alert('clicked') },
success: callback=> { console.log(callback) }
})
You can also use : one() instead of on() only if you don't use the clicked variable somewhere else. You attach the event for only one trigger. At the end of the callback you reattach it.
$(document).ready(function() {
function foo(e){
setTimeout(function () {
console.log("ajax done");
$(e.delegateTarget).one('click', '#submit-catalog', foo)
},1000)
}
$(document).one('click', '#submit-catalog', foo);
});
Other solution : add class to stop the propagation thanks to delegate event
$(document).ready(function() {
$(document)
.on('click', '#submit-catalog.prevent', function(e){
e.stopImmediatePropagation();
}
.on('click', '#submit-catalog', function(){
$(e.currentTarget).addClass('prevent');
setTimeout(function () {
console.log("ajax done");
$(e.currentTarget).removeClass('prevent');
}, 1000)
});
});

AJAX call before document.ready

I have a requirment where in AJAX call has to happen before document.ready and the response from the AJAX call will be used to update some HTML elements.
So I have something like below:
var ajaxget = $.ajax({
type: 'GET',
url:'/xxx/get',
success: function(resp) {
//logic
}
});
$(document).ready(function(){
$.when(ajaxget).done(function(resp) {
//do ur logic
$(documet).trigger("yyyy");
});
});
//the above part is common across pages and placed in the <head>
//below one goes into multiple places based on the pages
$(document).ready(function(){
$(document).on('yyyy', function() {
});
});
The issue is the trigger event "yyyy" doesn't get executed in IE and intermittently on other browsers as well. Please help!
Might be better to use then() instead of success to be sure that whatever happens in success is completed before the $.when.done
Note that success is not part of the promise chain
Try:
var ajaxget = $.ajax({
type: 'GET',
url: '/xxx/get'
}).then(function(resp) {
//logic
return resp;
});
$(document).ready(function() {
ajaxget.then(function(resp) {
//do ur logic
$(documet).trigger("yyyy");
});
});
But also note you are triggering the event before you register it also if the order shown in question is correct
This code works for me. Simply i defined "yyyy" event before triggering.
$(document).ready(function () {
$(document).on("yyyy", function () {
console.log('triggered');
});
$.ajax({
type:'GET',
url:'some.jsp',//your url
success:function(resp){
//logic
$(document).trigger("yyyy");
console.log(resp);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Is possible in on click function in jQuery wait for ajax complete and then do some code?

I want show modal after ajax is complete, here is my code:
$('.mymodalbtn').on('click', function (e) {
modalWindow = $(this).attr('data-target');
// alert(modalWindow);
$(document).ajaxStop(function () {
//0 === $.active
$(modalWindow).modal('show');
});
});
It is possible to do that? Now modal show after every ajax complete.
Thank you.
You can use .ajaxComplete() method of ajax request,which registers a handler to be called when Ajax request is completed.
Read more here.
Use complete event when your ajax call completed.
$('.mymodalbtn').on('click', function (e) {
modalWindow = $(this).attr('data-target');
$.ajax({
type: 'GET',
url: 'your_url',
success: function (responseData, textStatus) {
},
complete: function (textStatus) {
$(modalWindow).modal('show');
},
error: function (responseData)
{
}
});
});
I'm not sure about the way you're doing an ajax call, but I've been able to do it with the post super global
$_post(phpfile.php, $_post(phpfile.php, {variables to send}, function) you can use data as a parameter for the function and it will be anything that PHP echoes including error messages
Thank you for inspiration finally I do it this way.
global variable:
window.modal = "";
on click function:
$('.mymodalbtn').on('click', function (e) {
modalWindow = $(this).attr('data-target');
window.modal = modalWindow;
});
and ajax complete:
$(document).ajaxComplete(function (event, request, settings) {
if(window.modal != ""){
$(window.modal).modal('show');
window.modal = "";
}
});
Hope it is allright :-)
try to use setTimeout.
setTimeout(function(){
$('#mymodal').modal('show');
},4000);
Yes it is possible. You can use .ajaxStop() or .ajaxComplete() or in .ajaxSuccess()

$.when().then() not working with nested ajax calls

I have been trying to scroll the page to a dynamic div that is created by the an ajax call.
When #divnotifications div clicked (below), I make the first ajax call that adds the Post details, then within this ajax call, another ajax call is made to add the related comments to the div.
The part explained so far works great. Then, I use $.when().then() to scroll to a div item created based on the ajax calls. However, the page does not scroll to the element that was created by LoadCommentsForPost ajax call.
Did I get the logic of $.when().then() wrong?
$(document).on('click', '#divnotifications div', function (event) {
event.preventDefault();
$.ajax({
//other details
success: function (postid) {
$.when(DisplayPostWithFullDetails(postid)).then(function () {
//scroll to the content created by
//LoadCommentsForPost function nested
//inside DisplayPostWithFullDetails
});
}
});
});
function DisplayPostWithFullDetails(postId) {
$.ajax({
//other details
success: function (post) {
//The code to build the div to display the post -- working fine
LoadCommentsForPost(post.PostId);
}
});
}
function LoadCommentsForPost(postid) {
$.ajax({
//other details
success: function (response) {
var comments = JSON.parse(response);
DisplayComments(comments);//builds the div to display the comments - working fine
}
});
}
UPDATED CODE
After receiving some feedback, I ended up with the following code. However, it is still not working. It works only if I add some delay to make sure the div is loaded:
$(document).on('click', '#divnotifications div', function (event) {
event.preventDefault();
$.ajax({
//other ajax stuff
success: function (postid) {
DisplayPostWithFullDetails(postid).done(function () {
setTimeout(function () {
var scrollto = $("div[data-" + type.toLowerCase() + "displayform='" + relateditem + "']").offset().top;
$("html, body").animate({ scrollTop: scrollto }, 600);
}, 500);
});
}
});
});
function DisplayPostWithFullDetails(postId) {
jQuery.support.cors = true;
return $.ajax({
//other ajax stuff
success: function (post) {
post = JSON.parse(post);
//display the post details
LoadCommentsForPost(post.PostId);
}
});
}
function LoadCommentsForPost(postid) {
var promise = new $.Deferred();
jQuery.support.cors = true;
$.ajax({
//other ajax stuff
success: function (response) {
var comments = JSON.parse(response);
DisplayComments(comments);//this is not ajax
promise.resolve('loadedcomments');
}
});
return promise;
}
Did I get the logic of $.when().then() wrong?
Yes, you need to return a promise from the functions if you want to use the function with $.when:
function DisplayPostWithFullDetails(postId) {
return $.ajax({...
// ^^^^^^
That said, wrapping a single promise in $.when is useless.
$.when(DisplayPostWithFullDetails(postid)).then(function () {
should just be:
DisplayPostWithFullDetail(postid).then(function () {
Did I get the logic of $.when().then() wrong?
No, but you are NOT returning the promise so you can't use the promise functions like .then().
UPDATE:
I use $.when().then() to scroll to a div item created based on the ajax calls. However, the page does not scroll to the element that was created by LoadCommentsForPost ajax call.
For me this means that you need to wait that both ajax calls are resolved.
This fiddle show how it should work emulating the ajax call using setTimeout Fiddle.
Your code may look similar to:
function DisplayPostWithFullDetails(postId) {
var promise = new $.Deferred();
$.ajax({
//other details
success: function (post) {
//The code to build the div to display the post -- working fine
LoadCommentsForPost(post.PostId).then(function() {
promise.resolve();
});
}
});
return promise;
}
function LoadCommentsForPost(postid) {
return $.ajax({
//other details
success: function (response) {
var comments = JSON.parse(response);
DisplayComments(comments);//builds the div to display the comments - working fine
}
});
}
Now when you execute the function DisplayPostWithFullDetails it return a promise.
So you can use .then() method;
DisplayPostWithFullDetails(postid)).then(function () {});
or...
var promise = DisplayPostWithFullDetails(postid);
promise.then(function(data){});
Also the major advantage of use $.when() is that you can execute the .then() method when all the promises that you pass to it are resolved.
There are not need to use it when you are waiting for a single promise.

Toggle loader on $.post shorthand for Ajax call

I have this code for make a Ajax call:
$.post($form.attr('action'), $form.serialize(), 'json').done(function (data, textStatus, jqXHR) {
// Some logic here for done callback
// Redirect to another URL after 5 seconds
window.setTimeout(function () {
window.location = data.redirect_to;
}, 5000);
}).fail(function () {
// Some logic here for fail callback
})
That code works fine. Now I need to attach a "loader" to this Ajax call. I knew that I can attach this to $(document) as of jQuery 1.8+ docs expose (also found the same on this topic) so I have done the following:
$(function () {
// a bunch of logic here
}).ajaxStart(function () {
$('#loaderModal').modal('show');
$('#loaderModal').on('show.bs.modal', function (e) {
$('#loaderDiv').loader();
})
}).ajaxStop(function () {
$('#loaderModal').modal('hide');
$('#loaderModal').on('hidden.bs.modal', function (e) {
$('#loaderDiv').loader('destroy');
})
});
And once again that works but happens that I have other Ajax calls on the page (for validation purposes on some fields) and every time any of them run then the loader is show which is not correct since I need to attach only to the code shown above (the first piece of code). How I can accomplish this?
As a second part, an related to this post, some of the logic on done and fail callback trigger a Bootstrap Growl message and as you must have noticed I'm using the Twitter Bootstrap Modal component in which the loader is contained, so I'm fear that the call made to run the loader block in some way the second call when the callback for done is invoked, is that even possible? how fast is the execution of these events?
PS: If any of yours have a better solution to this then say and thanks in advance
Instead of using the global event handlers, show/hide the loader for the current ajax request like
//show the loader before the request
showLoader();
$.post($form.attr('action'), $form.serialize(), 'json').done(function (data, textStatus, jqXHR) {
// Some logic here for done callback
// Redirect to another URL after 5 seconds
window.setTimeout(function () {
window.location = data.redirect_to;
}, 5000);
}).fail(function () {
// Some logic here for fail callback
}).always(hideLoader) //hide the loader after the ajax request
function showLoader() {
$('#loaderModal').modal('show');
$('#loaderModal').on('show.bs.modal', function (e) {
$('#loaderDiv').loader();
})
}
function hideLoader() {
$('#loaderModal').modal('hide');
$('#loaderModal').on('hidden.bs.modal', function (e) {
$('#loaderDiv').loader('destroy');
})
}
Why not put your loading scripts into a function so you can call them at will? That way they fit into the logic of your code instead of running every time.
function startLoad() {
.ajaxStart(function () {
$('#loaderModal').modal('show');
$('#loaderModal').on('show.bs.modal', function (e) {
$('#loaderDiv').loader();
})
})
}
function stopLoad() {
.ajaxStop(function () {
$('#loaderModal').modal('hide');
$('#loaderModal').on('hidden.bs.modal', function (e) {
$('#loaderDiv').loader('destroy');
})
});
}

Categories

Resources