.js/jQuery RE: specifying ajax requests in ajaxStart

TechBoyJK

Lifer
Oct 17, 2002
16,701
60
91
Upon initiating ajax request, I want to trigger an overlay ONLY if it takes more than 2 seconds.

My goal is to only trigger the overlay after 2 seconds, and only if the ajax request has not completed.

The following works.

Once it fires off an ajax request, it waits 2 seconds. If there is still an active ajax request, it triggers an overlay with a 'waiting' gif. Once ajax requests are done, it hides the overlay.

However, the logic is based on ANY active ajax requests. How can I write this to only fire for a specific request? This code is vulnerable to other background ajax requests that I don't want firing an overlay. I need this to only work for specific ajax requests. For instance, if I have an ajax request that fires in the background, but isn't critical to the UI experience, I don't want it triggering the overlay.


Code:
$(document).on({

  ajaxStart:function() {

    setTimeout(function(){
      if (jQuery.active === 1) {
        $body.addClass("loading");
      }
    }, 2000);

  },

  ajaxComplete: function() {$body.removeClass("loading"); }    

});
 

purbeast0

No Lifer
Sep 13, 2001
52,855
5,727
126
Do the same logic but inside that specific Ajax request, not at the document level
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
Instead of binding the ajaxStart to the document object you need bind it to the specific DOM element that you want.

For instance, all of the items on the page you want to have that behavior could have a data attribute like "data-fade-on-slow" and then your JS could look like

Code:
$("[data-fade-on-slow").on({

  ajaxStart:function() {

    setTimeout(function(){
      if (jQuery.active === 1) {
        $body.addClass("loading");
      }
    }, 2000);

  },

  ajaxComplete: function() {$body.removeClass("loading"); }    

});
 

Sgraffite

Member
Jul 4, 2001
87
0
66
You probably don't want to modify ajaxStart() or ajaxComplete() at all if you aren't looking to do this globally. You can do it like this for a single ajax request (untested):

Code:
var loading = setInterval(function(){
	$('body').addClass('loading');
},2000);
var promise = $.post('/here',{data:'stuff'});
promise.done(function(){
	clearInterval(loading);
	$('body').removeClass('loading');
});

To take it a step further and make it more easily reusable you could create a wrapper function call that handles the logic for you, so your ajax request would look more like this:


Code:
toggleLoading(true); // toggle on
var promise = $.post('/here',{data:'stuff'});
promise.done(function(){
	toggleLoading(false); // toggle off
});