Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 558
Kzqai Avatar asked Feb 08 '10 06:02

Kzqai


2 Answers

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.

like image 144
Christian C. Salvadó Avatar answered Oct 02 '22 13:10

Christian C. Salvadó


Have a look at the excellent Text Change Event plugin from Zurb, purveyors of the highest quality jQuery goods.

like image 43
Rob Cowie Avatar answered Oct 04 '22 13:10

Rob Cowie