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

11,137

Solution 1

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.

Solution 2

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

Share:
11,137
Kzqai
Author by

Kzqai

I make a ninja game at ninjawars.net, am hirable at bitlucid.com, do art & origami when I can at dnaexmosn.deviantart.com, and code open source stuff on github at github.com/tchalvak Code in: node react php javascript python (some) html/css Learning currently: Css-grid npm packaging aka Tchalvak

Updated on June 02, 2022

Comments

  • Kzqai
    Kzqai about 2 years

    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?