Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make my live jQuery search wait a second before performing the search?

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?

like image 369
willdanceforfun Avatar asked Jul 23 '09 13:07

willdanceforfun


People also ask

How do you wait 1 sec in JavaScript?

To delay a function execution in JavaScript by 1 second, wrap a promise execution inside a function and wrap the Promise's resolve() in a setTimeout() as shown below. setTimeout() accepts time in milliseconds, so setTimeout(fn, 1000) tells JavaScript to call fn after 1 second.

Which function we use to hold or delay the execution of JavaScript code?

To delay a function call, use setTimeout() function. functionname − The function name for the function to be executed. milliseconds − The number of milliseconds.


3 Answers

Easy, using setTimeout. Of course you only want one timer going at once, so it's important to use clearTimeout at the beginning of the function...

$(function() {
  var timer;
  $("#searchMe").keyup(function() {
    clearTimeout(timer);
    var ms = 200; // milliseconds
    var val = this.value;
    timer = setTimeout(function() {
      lookup(val);
    }, ms);
  });
});
like image 149
Josh Stodola Avatar answered Sep 20 '22 13:09

Josh Stodola


You may be interested in my bindDelayed jQuery mini-plugin. It:

  • Allows you to specify a delay before kicking off the request
  • Automatically cancels any previous requests that were scheduled to go off
  • Automatically cancels any in-air XHR requests that were in progress when you make your request
  • Only invokes your callback for the latest request
    • If the user types "s", waits long enough for the request to go out, and then types "a", and the response for "s" comes back before the response for "sa" you won't have to deal with it.

The answer to the original question using bindDelayed would look like so:

// Wait 200ms before sending a request,
// avoiding, cancelling, or ignoring previous requests
$('#searchMe').bindDelayed('keyup',200,'/RPCsearch.php',function(){
  // Construct the data to send with the search each time
  return {queryString:this.value};
},function(html){
  // Use the response, secure in the knowledge that this is the right response
  $("#suggestions").html(html).show();
},'html','post');

In case my site is down, here's the plugin code for Stack Overflow posterity:

(function($){
  // Instructions: http://phrogz.net/jquery-bind-delayed-get
  // Copyright:    Gavin Kistner, [email protected]
  // License:      http://phrogz.net/js/_ReuseLicense.txt
  $.fn.bindDelayed = function(event,delay,url,dataCallback,callback,dataType,action){
    var xhr, timer, ct=0;
    return this.on(event,function(){
      clearTimeout(timer);
      if (xhr) xhr.abort();
      timer = setTimeout(function(){
        var id = ++ct;
        xhr = $.ajax({
          type:action||'get',
          url:url,
          data:dataCallback && dataCallback(),
          dataType:dataType||'json',
          success:function(data){
            xhr = null;
            if (id==ct) callback.call(this,data);
          }
        });
      },delay);
    });
  };
})(jQuery);
like image 32
Phrogz Avatar answered Sep 21 '22 13:09

Phrogz


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.

like image 34
tvanfosson Avatar answered Sep 21 '22 13:09

tvanfosson