Web designers must always keep usability in mind when designing web sites. A site must allow quick and easy access to information during the very short time that a site first holds a visitor's interest. Any confusion that ensues about where things are, and that person's business is gone. Providing a way to precisely search for what they need is an excellent way to provide that usability. What Chris Root explains in this article is a way for your visitors to find and select items contained in long lists. He will also suggest ways to expand this to searching within HTML or XML documents.
Auto-Complete
Many desktop applications have user interface controls that allow a user to find matches for things as they type. This feature can be very useful for long lists of items such as states, countries, streets or product categories. Many web browsers implement this sort of functionality in their address bars. As you type, web site address matches that are part of a list of recently visited sites appear in a menu below the address bar. This reduces the amount of time it takes to access information.
Another place this is implemented is in HTML select menus. Unfortunately this only works with the first letter typed, it is not implemented in all browsers on all platforms and it doesn't shorten the list of choices to only matches.
The script described in this article will allow a user to begin typing what they are looking for in a text box while a select menu updates itself with matches. In the example the list comes from the contents of the select menu but it can also come from other sources.
The HTML
The HTML for this project is pretty simple. You could however use this script several places in a large form with multiple lists of information with no trouble. This example uses a list of city streets.
<body onLoad="fillit(sel,entry)">
<div>Enter the first three letters of a street and select a match from the menu.</div>
<form><label>
Street
<input type="text" name="Street" id="entry" onKeyUp="findIt(sel,this)"><br>
<select id="sel">
<option value="s0001">Adams</option>
<option value="s0002">Alder</option>
<option value="s0003">Banner</option>
<option value="s0004">Birchtree</option>
<option value="s0005">Brook</option>
<option value="s0007">Cooper</option>
<!--and so on and so forth-->
</select></label>
</form>
</body>
</html>
When the text box registers a keyUp event, the find() function calls and passes two parameters, the id of the select menu and a reference to the text field.
For something like state information, allow the user the choice of using the auto-complete script or just selecting something from the menu, especially if they know the item they wish to select is at the top of the list. If someone lives in Alabama for instance, there is no need to have them enter the first three letters of their state when the item they want is at the top of the list of states. Fill the select menu (a list box can be used as well) with all the values and text labels that you want your user to choose from in the HTML code to start with.
Alternatively, depending on the information in the list, the choice may not be as obvious. In this case you could store it in an array only and the user would always need to select a match. If there was only one match, and that match was the correct one, they could leave the menu alone. Otherwise they would need to select from the available matches displayed in the menu.
The longer the list the more useful our script becomes. It has been tested with a list over 1000 city streets and had an acceptable performance, even on a not so modern machine. There is a minimum of two characters before a search will start. this helps reduce the number of matches shown after any given keystroke. This limit can be adjusted easily.
When the page loads, a function called fillit() is called.
//initialize some global variables
var list = null;;
function fillit(sel,fld)
{
var field = document.getElementByid(fld);
var selobj = document.getElementById(sel);
if(!list)
{
ar len = selobj.options.length;
field.value = "";
list = new Array();
for(var i = 0;i < len;i++)
{
list[i] = new Object();
list[i]["text"] = selobj.options[i].text;
list[i]["value"] = selobj.options[i].value;
}
}
else
{
var op = document.createElement("option");
var tmp = null;
for(var i = 0;i < list.length;i++)
{
tmp = op.cloneNode(true);
tmp.appendChild(document.createTextNode(list[i]["text"]));
tmp.setAttribute("value",list[i]["value"]);
selobj.appendChild(tmp)/*;*/
}
}
}
A global variable is initialized to null. This will hold an array that in turn holds two custom objects to hold our data. We then get a reference to our select menu and text field objects. If our array does not exist yet (the page has just loaded so it’s still null), then we get the number of options in our select menu, set the contents of the text field to empty and begin looping through the menu contents.
As we run through each menu option, an object is created that will hold both what is in the value attribute and the text of the option tag.
If however our list array already exists, we are calling the function in order to refill the menu with all the original data. An option element is created and a temporary container is initialized.
In the loop the select menu is reconstructed using DOM methods.
Finding a Match
The findIt() function does the searching. It accepts two arguments. The first is the name of the select menu, the second is the name of the text field.
function findit(sel,field)
{
var selobj = document.getElementById(sel);
var d = document.getElementById("display");
var len = list.length;
if(field.value.length > 2)
{
if(!list)
{
fillit(sel,field);
}
var op = document.createElement("option");
selobj.options.length = 1
var reg = new RegExp(field.value,"i");
var tmp = null;
var count = 0;
var msg = "";
for(var i = 0;i < len;i++)
{
if(reg.test(list[i].text))
{
d.childNodes[0].nodeValue = msg;
tmp = op.cloneNode(true);
tmp.setAttribute("value",list[i].value);
tmp.appendChild(document.createTextNode(list[i].text));
selobj.appendChild(tmp);
}
}
}
else if(list && len > selobj.options.length)
{
selobj.selectedIndex = 0;
fillit(sel,field);
}
}
The first step is to get references to the select menu and the text field. We also need the length of the list array.
If the number of characters in the text field is greater than 2 and the list array exists. Then the menu is cleared of it's content to prepare it for display of any matches. The number of options is set to one rather than 0 to allow for an option that is always there such as a “Select a Street” option.
A regular expression object is then created that will be used to look for a match at the beginning of a given string. Using this object to create a regular expression allows the use of a string from whatever source we wish to be used along with any regular expression characters. The first parameter in the object constructor is the regular expression the second is any flags such as "i" for making the search case insensitive. If you were searching something other than one or two word street names, state names or country names you would want to match the beginning of word boundaries using "\b" instead of "^".
A few utility variables are initialized and we then loop through each of the list items contained in the arrays. If there is a match, the values are used to fill a new copy of the option element we created before the loop started. One thing to note about setting the properties of option elements is that the text label of an option is not an attribute. You must use the optionelement.text syntax rather than setAttribute to set the text label for each option.
If the length of the text in the field is less than 2 characters then we need to determine if the list needs to be refilled with all the values. By doing this, you allow the user to give up on their search before typing more than two characters and manually select something from the menu if they wish. If the user selects the text in the field and clears it to start a new search this will trigger that action. The fillit function is called and the select menu is refilled.
Possible Mods
To make this script and user interface more like the auto-complete widget in a browser address bar, you could use a DHTML menu and provide keyboard control for selecting a match and updating the content in the text box with the selected match.
This script would allow searching in any array of information and with a little modification any HTML collection. Searchable FAQ's, API documentation or help systems could be achieved by searching content contained in a hidden IFrame, the main HTML document itself or an XML document loaded in the background using the HTTPRequest object.
Conclusion
As you can see using auto-complete widgets on a web site can allow a visitor quick access to information. Always be on the lookout for ways to improve the user experience for your visitors and they will continue to come back for more.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
More JavaScript Articles
More By Chris Root
developerWorks - FREE Tools! |
You'll get answers to many questions and more from David Barnes, Lead Evangelist for IBM Emerging Internet Technologies. David will discuss aspects of Web 2.0 that bring value to corporations, academia, and government. He'll also discuss IBM's vision around Web 2.0, including the importance of remixability and consumability. The discussion will culminate with examples of various IBM Software Group solutions you can use to get ahead of the Web 2.0 adoption curve. FREE! Go There Now!
|
|
|
|
Visit IBM developerWorks to download a free trial of the latest release of IBM Lotus Sametime Standard V8.0. Lotus Sametime Standard V8.0 is a platform for unified communications and collaboration that combines security features with an extensible, open solution including integrated Voice over IP, geographic location awareness, mobile clients, and a robust Business Partner community offering telephony and video integration. FREE! Go There Now!
|
|
|
|
Download a free trial version of IBM Rational Developer for System i V7.1, which provides a complete development environment for traditional i5/OS application development. IBM Rational Developer for System i is a new eclipse-based workstation offering for i5/OS application development that provides a comprehensive Integrated Development Environment for edit/compile/debug of traditional RPG/COBOL/C/C++ i5/OS applications. FREE! Go There Now!
|
|
|
|
Join this webcast to see how IBM Data Studio Developer and pureQuery can take the pain out of Java data access. uApplications developed using both Java and SQL have become a common requirement. Database connectivity using Java Database Connectivity (JDBC) to create an application is a multi-step tedious process, and tooling that covers both SQL and Java has been unavailable, until now. IBM Data Studio introduces the pureQuery platform: a high-performance, Java data access platform focused on simplifying the tasks of developing, managing, and optimizing database applications and services. FREE! Go There Now!
|
|
|
|
Analysts, architects, and developers who have existing COBOL or PL/I skills and want to extend those skills to deploy new workloads on the mainframe can use the IBM Enterprise Modernization Sandbox for System z to find hands-on walkthroughs of common real world scenarios. The scenarios provide examples of how to rapidly design, create, assemble, test, and deploy high-quality Web, Web services, portal, and SOA applications for IBM CICS, IBM IMS, and IBM WebSphere Application Server. FREE! Go There Now!
|
|
|
|
Join this webcast to discover the key requirements for successful change and release management. Learn how to extend your .NET environment to improve productivity and collaboration, and address core problems afflicting team development. In this webcast, we’ll review typical challenges faced by customers and how to resolve them with the IBM Rational Change and Release Management solution, including Rational ClearCase, Rational ClearQuest and Rational Build Forge. Replay is available for 9 months. FREE! Go There Now!
|
|
|
|
As organizations have grown increasingly dependent on online software, the risk of malicious attacks has also become far more serious. Fortunately, well-governed organizations can protect their Web applications by injecting vulnerability assessments and ethical hacks into their software development and delivery processes. This paper describes 12 of the most common hacker attacks and provides basic rules that you can follow to help create more hack-resistant Web applications. FREE! Go There Now!
|
|
|
|
You can now evaluate IBM Rational Asset Manager V7.0 online without installing or configuring it on your own system! Rational Asset Manager helps create, modify, govern, find, and reuse any type of development assets, including SOA and systems development assets. Rational Asset Manager helps you reduce software development costs and improve quality by facilitating the reuse of all types of software development-related assets. Visit developerWorks to learn more about this product and register to explore its capabilities online. FREE! Go There Now!
|
|
|
|
IBM Lotus Notes 8 provides a wide range of developers the ability to provide customized, integrated user interfaces via composite applications and via custom sidebar and toolbar plug-ins. This webcast provides you with tips and techniques to use with out-of-the-box capabilities of Lotus Notes 8, and survey how you can share useful components within your own company and within a larger community. FREE! Go There Now!
|
|
|
|
Join this webcast to learn how IBM Rational's Functional Testing solution enables you to implement automation your way, at your pace, with your existing staff. In this webcast, you’ll learn how you can eliminate redundancy of manual test scripts, reduce errors, and increase test coverage through test automation. After this presentation you will understand how IBM Rational Functional Testing solution can streamline your manual testing and make test automation easily attainable. FREE! Go There Now!
|
|
|
|
All FREE IBM® developerWorks Tools! |