I’ve got a search field. Right now it searches for every keyup. So if someone types “Windows”, it will make a search with AJAX for every keyup: “W”, “Wi”, “Win”, “Wind”, “Windo”, “Window”, “Windows”.
I want to have a delay, so it only searches when the user stops typing for 200 ms.
There is no option for this in the keyup
function, and I have tried setTimeout
, but it didn’t work.
How can I do that?
Executing a function after a certain amount of inactivity is known as debouncing. Debouncing can be helpful for many reasons. One of the most popular applications in web development is to execute a search or filter some results after a user has stopped typing text in a textbox.
The keyup event occurs when a keyboard key is released. The keyup() method triggers the keyup event, or attaches a function to run when a keyup event occurs.
The keyup event is sent to an element when the user releases a key on the keyboard. It can be attached to any element, but the event is only sent to the element that has the focus. Focusable elements can vary between browsers, but form elements can always get focus so are reasonable candidates for this event type.
I use this small function for the same purpose, executing a function after the user has stopped typing for a specified amount of time or in events that fire at a high rate, like resize
:
function delay(callback, ms) { var timer = 0; return function() { var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function () { callback.apply(context, args); }, ms || 0); }; } // Example usage: $('#input').keyup(delay(function (e) { console.log('Time elapsed!', this.value); }, 500));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <label for="input">Try it: <input id="input" type="text" placeholder="Type something here..."/> </label>
The delay
function will return a wrapped function that internally handles an individual timer, in each execution the timer is restarted with the time delay provided, if multiple executions occur before this time passes, the timer will just reset and start again.
When the timer finally ends, the callback function is executed, passing the original context and arguments (in this example, the jQuery's event object, and the DOM element as this
).
I have re-implemented the function using ES5 and ES6 features for modern environments:
function delay(fn, ms) { let timer = 0 return function(...args) { clearTimeout(timer) timer = setTimeout(fn.bind(this, ...args), ms || 0) } }
The implementation is covered with a set of tests.
For something more sophisticated, give a look to the jQuery Typewatch plugin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With