Using jQuery to search against different types of content (3)

This post is more than 2 years old.

I don't normally take blog entries into so many iterations, but after my last blog post I got some really cool feedback from Dan Switzer and Kevin Marino.

Dan mentioned an excellent bit of code called debounce. You should read Dan's post to learn more about it or check out the original author's post on the concept. The basic idea is that given some user interaction you want to ensure you don't "react" to it more than one in a period of time. This isn't throttling where you "back up" the calls so you only get one 1 every N seconds. Rather, the additional calls are essentially ignored. If you look at my search (here is a link to the second demo) with a network monitor enabled, you will see one search for every key press. While I wanted that, it may make sense to do things a bit slower, especially on a high traffic server. Debounce allows for that. I can still have 'search as you type' but slowed down a bit. I plan on putting the entire code base up with my changes, but here is an shortened version of how I added it to my application:

$("#searchField").keyup(debounce(function() { .... },250));

What I've done here is slightly modified the normal jQuery event handler syntax by wrapping the inline function with a call to debounce. 250 is the value by which things will be blocked. I go this value from Dan and it seemed like a good idea. In my testing this tiny little change worked very well. I still got a snappy search form but it seemed to run about half the network calls.

So what about Kevin's advice? He suggested using some form of caching on the client side. Now - this can get incredibly complex if you have a need for it. I decided to do something very simple. Every time I work with the result of a search, I take that generated string and store it in a variable. For example:

if(field in cache) { console.log(field + " was in cache"); $("#results").html(cache[field]); return; }

In the example above, "field" represents what we are searching for. I apologize - that isn't a great name for the variable. Later on we store to the cache in the handle result for my network call.

cache[field] = s;

So yeah - this is pretty trivial. You can imagine that over time, the cache will get big. In my opinion this simple solution should work ok. This is not GMail. User's won't be sitting here constantly searching again and again. They should - as far as I know - do some searches and click on a result. If they come back to search again the cache will be reset.

Given these two changes, the application should be even better than the original. It's going to be making quite a few fewer network calls between the user of the debouncer and the cache. Here's the entire front end code.

<script type="text/javascript" src=""></script> <script> $(document).ready(function() {

var debounce = function (func, threshold, execAsap) {
    var timeout;
    return function debounced () {
        var obj = this, args = arguments;
        function delayed () {
            if (!execAsap)
                func.apply(obj, args);
            timeout = null; 
        if (timeout)
        else if (execAsap)
            func.apply(obj, args);
        timeout = setTimeout(delayed, threshold || 100); 

if (!window.console) console = {};
console.log = console.log || function(){};
console.dir = console.dir || function(){};

cache = {};

//listen for keyup on the field
$("#searchField").keyup(debounce(function() {
	//get and trim the value
	var field = $(this).val();
	field = $.trim(field)

	//if blank, nuke results and leave early
	if(field == "") {
	console.log("searching for "+field);
	if(field in cache) {
		console.log(field + " was in cache");
	$.getJSON("search.cfc?returnformat=json&method=search&queryformat=column", {"string":field}, function(res,code) {
		var s = "";
		s += "&lt;h2&gt;Results&lt;/h2&gt;";
		for(var i=0; i &lt; res.ROWCOUNT; i++) {
			//display a blog entry
			if(res.DATA.TYPE[i] == "entry") {
				s += "&lt;p&gt;&lt;img src=\"blog.png\" align=\"left\"&gt;";
				s += "&lt;b&gt;Blog Entry: &lt;a href=\"\"&gt;" + res.DATA.TITLE[i] + "&lt;/a&gt;&lt;/b&gt;&lt;br/&gt;";
				s += res.DATA.SUMMARY[i];
				s += "&lt;br clear=\"left\"&gt;&lt;/p&gt;";
			//display a blog comment
			} else {
				s += "&lt;p&gt;&lt;img src=\"" + res.DATA.GRAVATAR[i] + "\" align=\"left\"&gt;";
				s += "&lt;b&gt;Comment by " + res.DATA.AUTHOR[i] + "&lt;/b&gt;&lt;br/&gt;";
				s += "&lt;b&gt;Blog Entry: &lt;a href=\"\"&gt;" + res.DATA.TITLE[i] + "&lt;/a&gt;&lt;/b&gt;&lt;br/&gt;";
				s += res.DATA.SUMMARY[i];
				s += "&lt;br clear=\"left\"&gt;&lt;/p&gt;";
		cache[field] = s;

}) </script> <style> #results p { border-style:solid; border-width:thin; padding: 10px; } </style>

<form> Search: <input type="text" name="search" id="searchField"> </form>

<div id="results"></div>

And as always, I've put up a demo for you to play with. Enjoy!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Gary Funk posted on 2/7/2011 at 3:31 AM

Will this make its way into BlogCFC?

Comment 2 by Raymond Camden posted on 2/7/2011 at 3:33 AM

I haven't thought about it - in terms of the front end. I _have_ wanted to bring in Solr though so results would be better.

Comment 3 by Kevin Marino posted on 2/7/2011 at 7:26 PM

Nice work. The debounce with the cache makes for a nice experience.

Comment 4 by Dan G. Switzer, II posted on 2/7/2011 at 7:26 PM

As I mentioned in your other blog entry, debouncing events is a great way to handle double-clickers too. If you have some functionality that you find people tend to double-click to start the event, debouncing the event can be used to cancel the multiple clicks.

This can be very useful on sites where you do a lot of AJAX-based updates and don't want to fire false events.

Comment 5 by mathew posted on 2/17/2011 at 3:09 PM

Hi Ray,
I need a help on one of the jquery issue.I'm unable to find out the solution of that.I'm very new to jquery.
I have a form and in that i have 'ADD,Update and search' buttons.Using search button, i'm populating the form fields and then when user clicks on the update button, he can update those populated form values.However the moment when i clicked on the update button,the focus is going back to search click event again.update click event is getting triggered but after that it's automatically going to the code inside the search click event.I written code for each button in their own click events only.I'm not able to find out why it's happening.I tried different things ,like after populating the form values [disabling the search button,removing the search button from DOM itself] but no luck.Could you please suggest how to handle this situation.Thanks in advance for your help!

Comment 6 by Raymond Camden posted on 2/17/2011 at 8:52 PM

I'd have to see your code to help. This is a bit off topic for this blog post so please use my contact form to send me additional information.