Idiomatic jQuery delayed event (only after a short pause in typing)? (aka timewatch/typewatch/keywatch)

Kzqai picture Kzqai · Feb 8, 2010 · Viewed 11.1k times · Source

Here is some jQuery for a search box that I expect is actually an antipattern, and am sure there is a much better solution for that I would love to be pointed towards:

I will describe it in comments then just give the code, since the comments may be more clear and simple than the code:

  • // set up a function call on keypress.
  • // function call has a delay before the main event occurs.
  • // When keypress function is called, wipe any previously queued events and make a new one at the standard delay rate.
  • // Use a global to store the setTimeout pointer.
  • // clearTimeout any pre-existing pointers.
  • // Start a new delay.

The Code:

                // set up a filter function call on keypress.
                $('#supplier-select-filter').keypress(function (){
                    // Currently, resets a delay on an eventual filtering action every keypress.
                    filterSuppliers(.3, this);
                });

                // Delayed filter that kills all previous filter request.
                function filterSuppliers(delay, inputbox){
                    if(undefined != typeof(document.global_filter_trigger)){
                        clearTimeout(document.global_filter_trigger);
                        // clearTimeout any pre-existing pointers.
                    }
                    // Use a global to store the setTimeout pointer.
                    document.global_filter_trigger = setTimeout(function (){
                        var mask = $(inputbox).val();
                        $('#user_id').load("supplier.php?action=ajax_getsuppliers_html&mask="+escape(mask)); 
                    }, 1000*delay); 
                    // Finally, after delay is reached, display the filter results.             
                }

The problems:

On an input box where a search term may consist of 10 characters on average, that's 10 calls to setTimeout in a half a second, which seems to be processor heavy, and in my testing is causing some noticeable performance issues, so hopefully there's a cleaner alternative?

.load() is simpler than taking in JSON and then generating html from the json, but maybe there is a better tool?

.keypress() doesn't seem to always trigger on things like backspace deletion and other essentials, so perhaps using keypress() on this input box isn't the ideal?

Answer

Christian C. Salvadó picture Christian C. Salvadó · Feb 8, 2010

I frequently use the following approach, a simple function to execute a callback, after the user has stopped typing for a specified amount of time::

$(selector).keyup(function () {
  typewatch(function () {
    // executed only 500 ms after the last keyup event.
  }, 500);
});

Implementation:

var typewatch = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

I think this approach is very simple, and it doesn't imply any global variables.

For more sophisticated usages, give a look to the jQuery TypeWatch Plugin.