I've never managed to find a really good jQuery based autocomplete plugins, especially one that is flexible and easily extensible. So when the jQuery UI team released 1.8 back in March, I was intrigued to find that they included - amongst other new widgets - an autocomplete widget. And it turns out to be pretty damn good, and flexible to boot.
So when I had a need to add the ability for a local data source for the autocomplete plugin that we use on ShermansTravel QuickSearch, I gave the new jQuery UI widget a go.
The jQuery UI Autocomplete widget can load in data in three ways... (examples taken straight from the jQuery UI docs)
In an array with local data:
Pass it an array with a list of strings, and it will use present a list of matching values based on your entered string.
$(function() {
$("#tags").autocomplete({
source: ["php", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl"]
});
});
A string, specifying a URL to get the data:
Pass it a string of a relative URL, and it will make an ajax call to that URL, passing it the users entered string.
$(function() {
$("#birds").autocomplete({
source: "search.php",
minLength: 3
});
});
Via a callback (function):
Pass it a callback and you can do pretty much anything you want. This example uses such a technique and caches the query results.
var cache = {};
$("#birds").autocomplete({
source: function(request, response) {
if (cache.term == request.term && cache.content) {
response(cache.content);
return;
}
if (new RegExp(cache.term).test(request.term) && cache.content && cache.content.length < 13) {
response($.ui.autocomplete.filter(cache.content, request.term));
return;
}
$.ajax({
url: "search.php",
dataType: "json",
data: request,
success: function(data) {
cache.term = request.term;
cache.content = data;
response(data);
}
});
},
minLength: 2
});
A Caching Autocomplete for Remote Data
What I really needed was a way to cache every single query when loading data in via an ajax call. The Autocomplete widget does not cache your returned query data at all, which means that an ajax call is made on every single key press. Even if you set the minLength to something like 3 - which will only trigger the autocomplete once the user has entered at least 3 characters - every character entered after that will trigger an ajax call.
So I came up with a somewhat simple, but effective caching strategy using the callback method for loading data.
var cache = {};
$("#birds").autocomplete({
source: function(request, response) {
var term = request.term.toLowerCase(),
element = this.element,
cache = this.element.data('autocompleteCache') || {},
foundInCache = false;
$.each(cache, function(key, data){
if (term.indexOf(key) === 0 && data.length > 0) {
response(data);
foundInCache = true;
return;
}
});
if (foundInCache) return;
$.ajax({
url: 'search.php',
dataType: "json",
data: request,
success: function(data) {
cache[term] = data;
element.data('autocompleteCache', cache);
response(data);
}
});
},
minLength: 2
});
Here we are saving the cache as a hash in the corresponding element using jQuery's data function. And we are doing this for every query performed. We first loop through each element of the cache, and check if any of the keys begin with the current search term. If we find something, then we call the passed response callback function, and return from the each loop.
If no cache is found for the current term, then we call the ajax as usual. But if we do find a matching key in the cache, then we don't call the ajax, and instead return the cached data.
Simple, but works nicely.
