views:

25

answers:

1

Alright so I've got this script sort of working. The ajax call works and the correct data is returned. The problem is that when keystrokes are pressed quickly (not real quickly, just normal typing speed), then the animations keep going back and forth, and every ajax call is still executed.

How can I make it so that:

1) the ajax calls don't stack up and 2) the fadein and fadeout animations don't keep stacking up

I have this javascript:

    $(document).ready(function(){

$t = $("#data-users");

$('#data-overlay').css({
  opacity : 0.5,
  top     : $t.offset().top,
  width   : $t.outerWidth(),
  height  : $t.outerHeight()
});

$('.loader').css({
  top  : ($t.height() / 2),
  left : ($t.width() / 2)
});

    $('.findit').keyup(function(){
        var search;
        search = $(this).val();
            $('#data-overlay').fadeIn();
            //get the data
            $.post(
            '/users/testajax',
            {
            search: search
            },
            function(responseText){
                $("#data-users").html(responseText);
                $('#data-overlay').fadeOut();
            },
            'html'
            );

    });
});
+1  A: 

Two suggestions: one is to use the .ajaxStart() and .ajaxComplete(), which ensures that if a second ajax call is queued, complete is only called once. But you may still see flicker, if the response time of the ajax call is less than the users typing speed.

You may also be getting continuous 'blinking' long after typing stops because multiple fadein/fadeout animations are queued. To avoid that use the stop(false,false) function.

To reduce the number of ajax calls (thus the number of fadein/fadeout as well) put a short delay on the keyup function so the ajax call is made after a short delay, and if a user types quickly, only one call is made.

Combining the three:

jQuery.fn.keyupQueue = function(callback, delay) {
    return this.each(function(){
        var timer = null;
        $(this).keyup(function() {
            if (timer)
                window.clearTimeout(timer);
            timer = window.setTimeout( function() {
                timer = null;
                callback();
            }, delay || 200);
        });
    });
};

$("#data-overlay").bind("ajaxSend", function(){
    $(this).stop(true,true).fadeIn();
}).bind("ajaxComplete", function(){
    $(this).stop(true,true).fadeOut();
});

$('.findit').keyupQueue(function(){
    $.post('/users/testajax', 
           { search: $(this).val() },
           function(responseText){
               $("#data-users").html(responseText);
           },
           'html'
          );
});
Chadwick
Perfect. Exactly what I was looking for. One thing I've changed is not using ajaxSend, since I don't want the user to have to wait for the delay to be over to start seeing the animation. Thanks so much.
Matthew