More jQuery Magic - Search Highlighting

So at first glance, which browser do you think we're using in the screenshot below? FireFox? Chrome? IE8?

It's actually IE6 and all that search highlighting is done via jQuery!

Now most modern browsers do some sort of highlighting now when you do a "Find On Page" search so this may not be the most incredible jQuery trick you see in your life -- but at the very least it's the most impressive jQuery trick on this page.

Highlighting The Page

If you're interested in following along, you can a demo of the approach used on this page.

In order to search the page we're going to need to a couple things...

  1. Check for user input.
  2. Use the search phrase and find matching text.
  3. Replace our matches with the new highlighted text.

Let's jump in.

Checking For Input

jQuery makes it easy to work with events that we're previously... well... a pain. The .keyup() function allows you to supply a delegate to monitor for changes to your search field. Below is the code you'll find in the example.

//snip ...

self.input.keyup(function(e) {
  if (self.search) { clearTimeout(self.search); }

  //start a timer to perform the search. On browsers like
  //Chrome, Javascript works fine -- other less performant
  //browsers like IE6 have a hard time doing this
  self.search = setTimeout(self.performSearch, 300);

});

//snip...

As you can see by the comment, we don't do the search each time the key goes down. IE6, bless it's heart, tries it's best to keep up but it's a losing battle. Instead, we use a short time out to check for when the search begins. In many ways this is a lot better anyways. It's fairly transparent to the user and saves undue strain on the browser.

Search And Find

Once we're ready to search, we need to check the user's input and format it as required.

//snip...

//create a search string
var phrase = self.input.val().replace(/^\s+|\s+$/g, "");          
phrase = phrase.replace(/\s+/g, "|");

//make sure there are a couple letters
if (phrase.length < 3) { return; }      

//append the rest of the expression
phrase = ["\\b(", phrase, ")"].join("");

//snip...

In this part we use the regular expressions to format our search phrase. Specifically, we're trimming it down and replacing spaces with "or". This makes sure that any phrase in the box is matched.

You may want to change this depending on your needs, for example, require all values to match, etc...

Find, Replace, Repeat

Once we have a valid search phrase, now it's time to actually replace the values on the page. You'll notice that I target specific types of elements since you don't want to search the entire document. Unlike a built in browser search option, this function actually makes changes to the markup. If you we're to highlight a value inside a textarea then you're going to end up with markup instead of a yellow block.

It's worth noting that this version only works with elements that don't have additional markup within them. Links, bold text, spans, etc... they are going to be wiped out by this. I'm working on another version that respects child elements, but for now - be warned.

The code below shows what we're doing to make this change.

//snip...

//find and replace with highlight tags
$("h1, h3, p").each(function(i, v) {

  //replace any matches
  var block = $(v);
  block.html(
    block.text().replace(
      new RegExp(phrase, "gi"), 
      function(match) {
        return ["<span class='highlight'>", match, "</span>"].join("");
      }));

});

//snip...

In this example I'm limiting my changes to a couple header tags and paragraphs. This helps me avoid things like my search bar at the top of the page. You could also create a class named .search and use that as a target.

The code starts by removing any existing highlighting classes from the element and then follows up by replacing any matches with a highlight tag.

Practical Uses... (tell me if you think of one)

I'll admit that this was written just to see what it would look like. Most browsers already have a search on page feature that can be used to achieve the same effect. However, there are a few places that something like this may be handy.

AJAX Search Field

Have a page that searches other pages on the site and shows them as an list below the search field? Why not search the page they are on at the same time and highlight possible results?

Client Side Highlighting

Showing lists of data? Why not highlight matching values when a user hovers over certain buttons and filter options? Give them a preview of things to come?

Highlighting? How About Formatting?

Why just highlight text? Why not use this as dynamic formatting for text? Give users a preview of a change they are getting ready to make when they roll over a button?

Think this could be useful? Who knows! But it just goes to show just how much you can do with just a little bit of jQuery!

June 25, 2009

More jQuery Magic - Search Highlighting

Post titled "More jQuery Magic - Search Highlighting"