Delay AJAX Searches with JavaScript’s setTimeout
I was recently creating a custom Dijit widget that required that a list get filtered during each keystroke instead of using the usual "Submit" button. The problem I ran into (and had anticipated) was that each keystroke made the list flicker and fire off numerous AJAX requests. The normal flow was:
D Da Dav Davu // Oops, mistyped! Dav Davi David David_ // Space David_W //...and so on
Users that type quickly don't need a list filtered during every keystroke -- that's a waste of client-side processing. The simple solution is to employ JavaScript's native setTimeout method to delay searches until a given idle-time has passed. Users who type quickly thus wont bog down the page.
// Add an onChange to the textbox to listen to typing/changes this.findTextbox.lastValue = ""; var timeout; dojo.connect(this.findTextbox,"onKeyUp",this,function(){ // Only fire change if value has changed var value = this.findTextbox.get("value"); if(value != this.findTextbox.lastValue) { // Save the "last" value this.findTextbox.lastValue = value; // Delay before search in the case of typing if(timeout) { clearTimeout(timeout); } // Start new time out timeout = setTimeout(function() { // Do the search! console.warn("Doing search for " + value + ", time waited"); // Process.... },this.findKeyDelay); } });
It's important to store the last value of the input so that "useless" keys like SHIFT, CONTROL, and others don't trigger a restart of the timer. If the key does change the value of the input element before the timer is met, the timer is clear and restarted! You'll notice that I do not ensure that a value is present -- that's because I want the field to return all results if the user filters something and then deletes the input! This type of timer solution will save loads of unwanted processing on both the client and server sides!
hi david! just curious, why you don’t provide any demo page in this post..?
I didn’t include one because the idea of it is simple:
1. When a key is pressed, and the string is longer than minimum length, start a timeout
2a. If the value is still the same after that time out, run the search
2b. If the value isn’t the same, clear the timeout and start it again.
It’s more the concept that the execution. An example wouldn’t explain much more.
Great tip! What value do you suggest setting the delay to?
I don’t have a steadfast, scientific number but I think 500 ms is a good number.
Check that — 200 ms is a better one. :)
hi David ! i have tried it at work, but i had prefer to use a periodical method instead of the “onKeyUp” event for checking if the value has changed or not. I think it’s usefull for copy/paste, what do you think about it ?
I’ve tried it here : http://www.rtl.fr/recherche (french website)
thanks!
Even better solution is that onkeyup, oninput and onpaste events you just blur and focus the input element. Like that onchange event is fired, which you can use for checking.
This sort of technique will become increasingly important because, I predict, more and more pages will use typeahead not only for search suggestions, but also to update actual page content. I already see examples of typeahead on ecommerce sites showing suggested products as a user types a search phrase.
I had to do this with an App that I was writing as well. I toss a 1 second timeout on it and it improved the slickness 100 fold. :)
Yep, I’ve found that I’m doing this more often than not.
This idea has a little problem attached to it.
I’m not sure if you noticed.
Lets say you set findKeyDelay to 1000ms.
Lets say, user types word “audi” and typing takes less than 1 sec.
In such case your search may get stuck …