10

What is the best way to put a delay on the showing of a ajax-loader gif. When I click a button the loader gif shows and hides even if the time taken is a few hundred milli-seconds, this gives the browser a kind of flicker. What I want is to say only show the gif if it takes more than say 1000 milli-seconds to complete the ajax request.

 <script type="text/javascript">
     $(document).ready(function() {
         $('#loader').hide();
         $('#btnGetPeople').click(function() {
            $('#loader').show();
             $.getJSON("/User/GetName/10",
                null,
                function(data) { showPerson(data); });
         });
     });

     function showPerson(data) {
         alert(data);
         $('#loader').hide();
     }
</script>

My loader div contains....

<div id="loader"><img alt="" src="/content/ajax-loader.gif" /></div>

What is the best technique to achieve this?

Rippo
  • 22,117
  • 14
  • 78
  • 117

4 Answers4

22

As you can see I added a timeout which delay showing for 300ms. If ajax is faster the timeout is cancelled before the loader gets really shown.

<script type="text/javascript">
    var showLoader;
    $(document).ready(function() {
        $('#loader').hide();
        $('#btnGetPeople').click(function() {
            // only show loader if ajax request lasts longer then 300 ms
            showLoader = setTimeout("$('#loader').show()", 300);
            $.getJSON("/User/GetName/10",
                null,
                function(data) { showPerson(data); });
        });
    });

    function showPerson(data) {
        clearTimeout(showLoader);
        alert(data);
        $('#loader').hide();
    }
</script>
jitter
  • 53,475
  • 11
  • 111
  • 124
5

Here is a fun way to do it. Replace $loader.show() with this:

$("#loader").data('timeout', window.setTimeout(function(){ $("#loader").show()}, 1000));

And your hide command with this:

window.clearTimeout($("#loader").hide().data('timeout'));
Doug Neiner
  • 65,509
  • 13
  • 109
  • 118
  • @dcneiner, quick q - what is 'timeout'? – Rippo Dec 05 '09 at 08:26
  • Just a custom `data` attribute to keep the `int` returned from `setTimeout` associated with our DOM object. It is either this or declare another variable like @jitter. I just wanted to show a contained way of doing it with jQuery. – Doug Neiner Dec 05 '09 at 08:28
  • @RageZ `clearTimeout` only works when passed the same `integer` that was returned from the `setTimeout` function. Since I am storing the `integer` in a custom `data` attribute, it would work fine. – Doug Neiner Dec 05 '09 at 08:29
  • Doh! Forgot the timeout length... updating my answer :) – Doug Neiner Dec 05 '09 at 08:31
  • Thanks man :) At the least you will think of possibly using the `data` feature in the future. Good luck with your project! – Doug Neiner Dec 05 '09 at 08:35
  • @Doug, great idea using data! +1 for sure. I like not having a global timerid variable. Thanks for posting that. – fehays Nov 24 '10 at 21:36
1

You could also do it like this.

var loadingTimer;

$(document).ready(function () {

    $("#loader").ajaxStart(function () {
        loadingTimer = setTimeout(function () {
            $("#loader").show();
        }, 200);
    });

    $("#loader").ajaxStop(function () {
        clearTimeout(loadingTimer);
        $(this).hide();
    });

}
0

Thought I'd share something I did for this. I had a situation where I needed to do more than just show or hide the one element. So I used bind to create custom events for the loader:

$("#loader").bind("delayshow", function (event, timeout) {
    var $self = $(this);
    $self.data('timeout', setTimeout(function () {
        // show the loader
        $self.show();
        /* 
            implement additional code here as needed
        */
    }, timeout));
}).bind("delayhide", function (event) {
    // close and clear timeout
    var $self = $(this);
    clearTimeout($self.hide().data('timeout')); 
    /*
        implement additional code here as needed 
    */
});

// show it with a 500 millisecond delay
$("#loader").trigger('delayshow', 500);

// hide it
$("#loader").trigger('delayhide');
fehays
  • 3,147
  • 1
  • 24
  • 43