Autocomplete is a feature in web applications which predicts the rest of a word or sentence while the user is still typing. Users usually press the tab key to accept a suggestion, or the down arrow key to accept one of several.
In this tutorial we will look at how to use the Awesomplete JavaScript library to create an autocomplete widget in our websites. Awesomplete is created by Lea Verou, a well-known speaker, author and invited expert in the W3C CSS working group.
Why Not Use the HTML5 datalist
Element?
The HTML5 datalist element is possibly the simplest way to implement an autocomplete feature in a website. Unfortunately, browser support for this element is limited and it’s implementation is inconsistent (e.g. Chrome matches only from the start, Firefox anywhere). It’s also not possible to style it according to your website’s design and, although promising, it’s probably not the right choice yet.
Awesomplete, on the other hand, is an ultra lightweight, customizable autocomplete widget, which you can drop into your pages. It has zero dependencies (no jQuery), works across all modern browsers and can be styled according to your website’s theme.
So what are we waiting for? Let’s dive in!
Including Awesomplete in Your Web Page
To use the Awesomplete library we need two files: awesomplete.css
and awesomplete.js
.
You can get these using bower:
bower install https://github.com/LeaVerou/awesomplete.git#gh-pages
By downloading them from the Awesomplete website directly.
Or, by including them via the RawGit CDN (which serves raw files directly from GitHub with proper Content-Type headers). This is demonstrated below.
To instantiate the basic widget, you need an input element with a class of awesomplete
, followed by the assosciated options in a datalist element. The list
attribute of the input element must match the id
of the datalist element. This is a sensible default configuration, as it offers a fallback to any users with JavaScript disabled.
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.rawgit.com/LeaVerou/awesomplete/gh-pages/awesomplete.css">
</head>
<body>
<input class="awesomplete" list="mylist" />
<datalist id="mylist">
<option>One</option>
<option>Two</option>
<option>Three</option>
</datalist>
<script src="https://cdn.rawgit.com/LeaVerou/awesomplete/gh-pages/awesomplete.min.js"></script>
</body>
</html>
Basic Functionality
There are many ways to use this versatile library. Let’s start with a basic use case.
Using the data-list
Attribute
It is possible to move the options from the aforementioned datalist element into a data-list
attribute on the input element itself.
<input class="awesomplete"
data-minchars="1"
data-maxitems="5"
data-list="China, India, Japan, Russia, UK, USA" />
See the Pen Awesomplete (1) by SitePoint (@SitePoint) on CodePen.
Using JavaScript
The above solutions are useful if your autocomplete options are static. However. to create the list dynamically and further customize the behavior of the autocomplete widget, we need a JavaScript method.
<input id="countries" />
var input = document.getElementById("countries");
var awesomplete = new Awesomplete(input, {
minChars: 1,
maxItems: 5,
autoFirst: true
});
awesomplete.list = ["China", "India", "Japan", "Russia", "UK", "USA"];
Here we are creating a Awesomplete
object, passing it two parameters: a reference to our input element, and an object literal containing the configuration options.
We then assign the list
property of our Awesomplete
object to an array holding the list of the autocomplete options. In the demo below, I have expanded the array of country names, using this handy snippet.
Also, note that the minChars
, maxItems
and autoFirst
properties are same as the data-minchars
, data-maxitems
and data-autofirst
attributes in the previous demo.
See the Pen Awesomplete (2) by SitePoint (@SitePoint) on CodePen.
When using JavaScript to instantiate an autocomplete widget we have access to many other properties, APIs and events. Let see what are they are how to use them?
Extended JavaScript Properties
There are four other properties supported by the Awesomplete
object. They are: filter
, sort
, item
and replace
. These four properties have functions assigned to them.
The filter
property controls how entries get matched. Its callback function takes two parameters: the current suggestion text (so in our example each of the values “China”, “India”, “Japan”, “Russia”, “UK”, “USA” in turn) and a string containing the user’s input. By default, the input can match anywhere within the string and it’s a case insensitive match.
The following example demonstrates how you would make Awesomplete perform a case-sensitive match:
function myFilterFunc(text, input) {
return text.indexOf(input) > -1;
}
var input = document.getElementById("countries");
var awesomplete = new Awesomplete(input, {
filter: myFilterFunc
});
awesomplete.list = ["China", "India", "Japan", "Russia", "UK", "USA"];
The sort
property controls how list items are ordered. Its callback has the same prototype as the Array.prototype.sort() function.
Here’s how you would use it to sort matches in reverse alphabetical order:
function mySortFunc(text, input) {
return text < input;
}
var input = document.getElementById("countries");
var awesomplete = new Awesomplete(input, {
sort: mySortFunc
});
awesomplete.list = ['Albania', 'Brazil', 'Chile', 'Denmark', 'Egypt'];
The item
property controls how list items are generated. This callback also has two arguments: the current suggestion text and user’s input. It should return a list item. Here’s how you would use the item
property to highlight user input within a suggestion text:
function myItemFunc(text, input){
return Awesomplete.$.create("li", {
innerHTML: text.replace(RegExp(input.trim(), "gi"), "<mark>$&</mark>"),
"aria-selected": "false"
});
}
var input = document.getElementById("countries");
var awesomplete = new Awesomplete(input, {
item: myItemFunc
});
awesomplete.list = ["China", "India", "Japan", "Russia", "UK", "USA"];
The fourth and final property is the replace
property. The replace
property controls how the user’s selection replaces the user’s input. In contrast to the previous three functions, this callback takes one parameter: the text of the selected option. It is fired when the user selects one of the suggested options (e.g. by clicking on it).
Here’s how you would use it to transform a user’s selection to upper case:
function myReplaceFunc(text) {
input.value = text.toUpperCase();
}
var input = document.getElementById("countries");
var awesomplete = new Awesomplete(input, {
replace: myReplaceFunc
});
awesomplete.list = ['Albania', 'Brazil', 'Chile', 'Denmark', 'Egypt'];
Tying It All Together
Here is an demo showing how to combine the filter
and item
functions to only make a suggestion once a user has entered a specified character(s) (in this case a comma followed by a space):
See the Pen Awesomplete (3) by SitePoint (@SitePoint) on CodePen.
Digging Deeper — Events, APIs and Ajax
There are five custom events that are fired by this library. These are: awesomplete-select
, awesomplete-selectcomplete
, awesomplete-open
, awesomplete-close
and awesomplete-highlight
.
This is how you would hook into each of these events:
window.addEventListener("awesomplete-select", function(e){
// User made a selection from dropdown.
// This is fired before the selection is applied
}, false);
window.addEventListener("awesomplete-selectcomplete", function(e){
// User made a selection from dropdown.
// This is fired after the selection is applied
}, false);
window.addEventListener("awesomplete-open", function(e){
// The popup just appeared.
}, false);
window.addEventListener("awesomplete-close", function(e){
// The popup just closed.
}, false);
window.addEventListener("awesomplete-highlight", function(e){
// The highlighted item just changed
// (in response to pressing an arrow key or via an API call).
}, false);
Awesomplete provides various methods on the Awesomplete
object that allow you to customize its behavior:
open()
: Used to open the popup.close()
: Used to close the popup.next()
: Used to highlight the next item in the popup.previous()
: Used to highlight the previous item in the popup.goto(i)
: Used to highlight the item with indexi
in the popup (-1 to deselect all).select()
: Used to select the currently highlighted item, replace the text field’s value with it and close the popup.evaluate()
: Used to evaluate the current state of the widget and regenerate the list of suggestions. Closes the popup if none are available. This method is particularly useful if you dynamically set thelist
property while the popup is open.
Note: open()
will not currently open the list before an input event has fired, but there is a pull request on the project’s home page which should fix this.
The Finale
By way of a final example, this is how you might use Awesomplete in conjunction with data fetched from a remote API via Ajax. I will be using the REST Countries API, which provides users with a whole host of country data.
The first thing to do is to initialize the widget without setting its list property (I’m using jQuery here for the sake of brevity):
var input = $("#countries");
var awesomplete = new Awesomplete(input, {
minChars: 1,
autoFirst: true
});
Then, attach a keyup
event listener:
$(input).on("keyup", function(){ ... }
When the user has pressed a key, we need to grab the value of the input element and make our request:
$.ajax({
url: 'https://restcountries.eu/rest/v1/name/' + this.value,
type: 'GET',
dataType: 'json'
})
Within the success callback, we can iterate over the JSON response, grab the names of the respective cities and set the list property of the Awesomplete
object on the fly:
.success(function(data) {
var list = [];
$.each(data, function(key, value) {
list.push(value.name);
});
awesomplete.list = list;
});
And that’s it!
See the Pen Awesomplete (4) by SitePoint (@SitePoint) on CodePen.
Conclusion
In this tutorial, we have seen how easily we can implement an autocomplete widget in our projects using the lightweight and customizable Awesomplete library. The project is still being actively maintained and I encourage you to check it out.