jQuery UI – Autocomplete | Filter by split terms

Overview

jQuery UI has some cool widgets. One of the most popular is autocomplete. Out of the box it has the default behavior to filter results based on the searched term. This works great if your source list only contains a word or two. What if your autocomplete list has several words? What if instead of filtering based off a search string, that string was split apart at a space to create multiple terms?

Modify the default behavior

We can modify the way that filtering happens by extending the ui.autocomplete widget and overwriting the filter function:

//overrirde jQuery autocomple's filter function to filter based on words instead of a single string
$.extend( $.ui.autocomplete, {
	filter: function(array, term) {
		var arraySub=term.split(' ');//split searching on a space character

		//generate a regex, including each searched term
		var regEx = '^';
		for (i = 0; i < arraySub.length; i++) {
			regEx += '(?=.*' + $.ui.autocomplete.escapeRegex(arraySub[i]) + '.*)';
		}
		regEx += '.*$';
		
		var matcher = new RegExp(regEx, 'i');
		return $.grep( array, function( value ) {//filter elements which match our expression
			return matcher.test( value.label || value.value || value );
		});
	}
});

Now that we have filtering in place by the split term instead of full string, it would also be helpful to bold and color the matched term. We can do that by modifying the _renderItem function:

//Add formatting to matched terms
$.widget('ui.autocomplete', $.ui.autocomplete, {
	_renderItem: function (ul, item) {//Adjust to highlight ALL matches INSTEAD of only displaying
		var arraySub=this.term.split(' ');//split searching on a space character

		//generate a regex, including each searched term
		var regEx = '';
		for (i = 0; i < arraySub.length; i++) {
			if (i==0) {
				regEx += '(';
			} else {
				regEx += '|(';
			}
			regEx += $.ui.autocomplete.escapeRegex(arraySub[i]) + ')';
		}
		
		//Return listed result in class 'ui-autocomplete-term' which can then be styled using CSS
		return $('<li>')
			.append($('<div>').html(item.label.replace(new RegExp(regEx, 'gi'), '<span class="ui-autocomplete-term">$&</span>')))
			.appendTo(ul);
	}	
});

Finally, we can color our matched term with CSS:

.ui-autocomplete-term {
    font-weight: bold;
    color: blue;
}

A full example of this can be found here: https://jsfiddle.net/ba3yskze/