An HTML5-style "Google Suggest"
- Update, January 10th 2011: The ability to use an external source for a
<datalist>
has been removed from the HTML5 spec to reduce complexity. It can still be implemented usingXMLHttpRequest
to fetch data and then adding<option>
elements dynamically, but we may see it return as a native HTML5 feature at some point in the future. - Minor update on 26th April 2010.
Introduction
HTML5 is the next major revision of HTML (and XHTML) and is being jointly developed by the WHATWG and W3C HTML WG (as such, it is a work in progress, but this article will simply refer to it as HTML5.) I have already covered the basics of HTML forms in my previous article, improving your forms using HTML5, so this article will look at some more advanced aspects of HTML5 data input constructs, culminating in an example that shows how to build an auto-complete style text box using nothing more than a short server-side script and a few lines of markup.
The features discussed in this article were part of the Web Forms 2 specification, which is now part of W3C's HTML5 specification. The feature runs on Opera 9.5 or later. To test it, grab the latest version of Opera.
Combo boxes (input list
)
Let's start off with some background information - first of all, let's look at how HTML5 deals with combo boxes:
<input list="languages" name="language">
<datalist id="languages">
<option value="Norwegian"></option>
<option value="Dutch"></option>
<option value="English"></option>
</datalist>
In older browsers this will degrade to a simple text field. In newer user agents supporting HTML5 however you will be able to select one of the predefined values in addition to being able to type something in yourself. This functionality is very similar to that offered in e-mail clients and the address bar of the browser for instance. If you need this functionality but your suggested options need to be presented in older browsers as well you might want to consider the following markup (this has some additional context added as well):
<datalist id="languages">
</datalist>
Browsers supporting the list
attribute / datalist
element construct of HTML5 will not display the datalist
element and its contents, instead carefully extracting the option
element values out of it to populate the combo box. Older browsers will render the contents of the datalist
element and allow the user to use either the input field or select an option.
External source for datalist
Another interesting feature is that you can let the suggestions be populated from an external XML file. The external XML file looks something like the following (it needs to be served with an application/xml
media type):
<select xmlns="http://www.w3.org/1999/xhtml">
The contents of this select
element will then replace the contents of any datalist
that references it unless the select
element in the external file has its type
attribute set to incremental
in which case the contents will be appended to, and not replace, existing content. You can tell the user agent to populate a datalist
element with an external file called foo using something like this:
<input list="languages" name="language">
<datalist id="languages" data="foo"></datalist>
(select
elements have also been extended with a data
attribute in HTML5, in case you were wondering.)
The source code for the above examples can be found in the example files that accompany this article, found here. In addition, a live demo is available at http://html5.org/demos/dev.opera.com/article-examples.html.
A dynamic combo box
So far we have looked at combo boxes and a way to populate them using an external file. All we need now to emulate Google Suggest in HTML5 is an event to listen to the combo box and a small script on the server to dynamically generate the file that will populate the datalist
element. Using conventional techniques you would need to create your own "dropdown menu" listing the various options, use XMLHttpRequest
to fetch the external data, and write code to parse this data to populate the menu - a lot of work, I'm sure you'll agree.
So what event can we use? Web Forms 2 introduces an event called input
, which is already supported by several browsers, including Opera. The event dispatches after the user inputs some text using the keyboard. For rapid keyboard input (entering multiple characters) a single event is dispatched. Integrating the event in our combo box makes the code a tad more complicated:
<input list="suggest" name="q"
oninput="list.data = '?w=' + encodeURIComponent(value)">
<datalist id="suggest"></datalist>
As you can see the input
event handler manipulates list.data
. The list
attribute on the input
element refers to the datalist
element by its id
, so it knows what it is populating. All we need to do to load the data from the specified location is manipulate the data
attribute - the location is ?w
plus the user input, which is encoded into a URI compatible syntax using the encodeURIComponent
function (part of the global object). So if the user enters foo the URI fetched will be ?w=foo
(resolved relative to the URI of the page the script runs on). A server-side file receives this URI, searches a text file full of possible words for this text string, and then returns an XML file containing the words that contain the text string, to populate the datalist. This all happens nice and dynamically, so as soon as you change the search term inside the text input, the server-side file processes the new search term and sends an updated XML file, changing the contents of the datalist
element accordingly.
I've provided a working example of this for you to try out yourselves - download the files from here, or check out the live demo at http://html5.org/demos/dev.opera.com/article-example-suggest.py.
The files for this example are:
- A newline-delimited file of suggestions called suggest.txt, which will be parsed when the script searches for the user-entered search term
- A Python script called article-example-suggest.py, which parses the textfile looking for the user-entered search term, and then returns the XML search results. This file also contains the input and datalist elements discussed above
The full python code file looks like this:
import os
qs = os.environ["QUERY_STRING"]
# The page as shown by default
main="""Content-Type:text/html;charset=UTF-8\n
<!doctype html>
<html>
<head>Demo </head>
<body>
<p>
<datalist id="suggest"></datalist>
</p>
</body>
</html>"""
if qs=="":
print main
else:
# If a query string was provided we need to provide an XML file with
# options filtered using the user input
import sys
print "Content-type: application/xml"
print "Cache-control: no-cache"
print ""
sys.stdout.write('<select xmlns="http://www.w3.org/1999/xhtml">')
sys.stdout.write(' ' % qs[2:])
for name in open('suggest.txt').readlines():
if name.lower().find(qs[2:].lower())!=-1:
sys.stdout.write('' % name)
sys.stdout.write('</select>')
Summary
I hope you enjoyed these examples! (Many thanks to Johannes Hoff (Core developer at Opera) for writing the above Python script after I hinted in a presentation that Google Suggest was only a few lines of code using HTML5 - turned out to be true both on the client and server.) They are not ready for mass production yet, but they do give you another interesting taste of what is to come with HTML5.
This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
Comments
The forum archive of this article is still available on My Opera.