Wednesday, November 20, 2013

jQuery UI: Highlighting Autocomplete Text

When a user types in an autocomplete text input field, the matching items are presented in a menu, just beneath the input. For example, the default autocomplete example uses an array of programming language strings as the source, so if you type "f", you'll get a menu displaying all items containing the letter "f" — doesn't matter where the "f" is located in the string, only that it's there. Sometimes, it's nice to see the matching portion of the item explicitly highlighted. Can we do this using the jQuery UI autocomplete widget?

By extending the autocomplete widget to provide a new option, and to override the _renderItem() method, we can highlight the portion of the menu items that matches the user's query. This example shows us just how it's done. The option we're introducing into the widget allows us to specify which class to apply to the highlighted portion of the text. The default is ui-state-highlight.


Here you can see that the user has typed "fu" into the autocomplete text box. Notice the highlighted "Fu" in the resulting drop-down menu. We can also pass in our own class to make the text, bold, for example.


Let's take a peek at what's involved in implementing a custom _renderItem() method to provide this functionality.

_renderItem: function( ul, item ) {

    var re = new RegExp( "(" + this.term + ")", "gi" ),
        cls = this.options.highlightClass,
        template = "<span class='" + cls + "'>$1</span>",
        label = item.label.replace( re, template ),
        $li = $( "<li/>" ).appendTo( ul );
           
    $( "<a/>" ).attr( "href", "#" )
               .html( label )
               .appendTo( $li );
            
    return $li;
            
}

The first thing we do inside _renderItem() is set up a bunch of variables. Let's take a look at what each one means.

  • re — a regular expression, used to find and capture the query string withing the item label
  • cls — the class applied to any matching text
  • template — a new span element we'll replace the query string with inside the label
  • label — the resulting HTML we'll pass to the menu item
  • $li — the resulting li element used by the menu
The key to this functionality is the way the regular expression and span template work. Note the $1 inside the span template — this is the text captured by the regular expression — the text the user has typed. Before we return the $li element we've just created, we need to set the html on a link element, since this is the structure the menu expects.