tags:

views:

805

answers:

5

Hi everyone,

I've got a search input which sends data from an input to a php file as I type. The php file does a search on my database and shows up a list of search options. You know, the ajax style live searching.

My problem is, if you type something really fast, it might just conduct a search off of the first 1 or 2 letters even though another 10 have been typed. This causes a few problems.

My jquery looks a bit like this:

$(document).ready(function(){
$('#searchMe').keyup(function(){

 lookup(this.value);

});
});

and

function lookup(searchinput) {



 if(searchinput.length == 0) {
    // Hide the suggestion box.
    $("#suggestions").hide();
 } else {

$('#loading').fadeIn();


    $.post("/RPCsearch.php", {queryString: ""+searchinput+""}, function(data){
        if(data.length > 0) {
            $("#suggestions").html(data).show();
            $('#loading').fadeOut();
        }
    });
}
} // lookup

So I'm just curious, how can I make it so that my script waits until I've finished typing before running the function? My logic says something like if a key hasn't been pressed for 200 micro seconds, run the function, otherwise hold up a bit.

How is this done?

+1  A: 

1 solution in psuedocode:

OnKeyPress()
    txt = getTxt
    sleep(200)
    newTxt = getTxt
    if (txt == newTxt)  // nothing has been typed so do something
       run my thing
Alan Jackson
+2  A: 

You really ought to look at using the jQuery autocomplete plugin. I find this plugin to be very useful and it already does what you need. Look particularly at the delay option, which you can customize to change how long the plugin waits after a keystroke to run.

tvanfosson
cheers, i would use a plugin i just thought its such a small thing to do and i had half the code in place already there wasn't much point to installing one. thanks anyways!
cosmicbdog
+9  A: 

Easy, using setTimeout. Of course you only want one timeout going at once, so you must use clearTimeout at the beginning of the function...

$(document).ready(function(){
  $("#searchMe").keyup(function() {
    clearTimeout($.data(this, "timer"));
    var ms = 200; //milliseconds
    var val = this.value;
    var wait = setTimeout(function() {
      lookup(val);
    }, ms);
    $.data(this, "timer", wait);
  });
});

Note: I am using jQuery.data to "store" the timer variable, as opposed to using a global.

Josh Stodola
Thanks heaps for this Josh. a few new things in there I haven't seen!
cosmicbdog
worked a treat.
cosmicbdog
A: 

I have found the best success when attaching the event to keypress, keydown, and keyup inputs. Safari/FireFox/IE all seem to handle special keypresses (delete, backspace, etc.) a bit differently but using all events together seems to cover it. The only way that running all events works though is to use setTimeout so that when they all fire it just resets the timer and ultimately the callback only gets executed once.

var delay = 200;
var search_timer = null;
$("#searchMe").keydown(function(e) {
    if(search_timer) {
        clearTimeout(search_timer);
    }
    search_timer = setTimeout(lookup, delay);
});
$("#searchMe").keypress(function(e) {
    if(search_timer) {
        clearTimeout(search_timer);
    }
    search_timer = setTimeout(lookup, delay);
});
$("#searchMe").keyup(function(e) {
    if(search_timer) {
        clearTimeout(search_timer);
    }
    search_timer = setTimeout(lookup, delay);
});
Ty W
A: 

this one is happy

 $(document).ready(function(){

   $("#searchMe").keyup(function () {

  try{window.clearTimeout(timeoutID);}catch(e){}
  timeoutID = window.setTimeout(run, 2000); //delay

  function run()
  {      //dowhatev
    var text = $("#searchMe").val();
    //$("#showit").html(text);       
  }     
 });   
});
spence