This page has been archived. For the latest news on FormAssembly, go to: http://www3.formassembly.com/blog

Ajax Makeover: Adding a Smart Type Ahead

[Jump to the demonstration page]

If you are like me, you probably have a hard time doing a realistic estimate
of the time you spend on any given task. That’s why Time Tracking
applications were invented… to help you manage and plan your projects
better. Unfortunately, their very existence collides with the way people
like to think and to work. Freely. Without the constraints of a ticking
clock. Making a web application that is actually helpful is going to
be quite a challenge for this makeover.

The first aspect of time tracking application I’m going to cover
is the task input. Chances are, there is a somewhat small set of tasks
that are part of your daily routine: deleting spams, writing status reports,
attending meetings, debugging code, etc… If you were able to make
an exhaustive list, you could populate a <select> field and that
would be your task input.
Of course (or hopefully), your job is not that predictable, and there are
lots of other way for you to spend your time at work. To describe these tasks,
you need a free text input.

The point of the type-ahead functionality (or auto-complete) is to combine
these two needs (predefined list and free text) in one field. The type-ahead
becomes ’smart’ when it learns from previous inputs and other
users and guesses your intent after just a couple keystrokes.

Before going into technical details, you may want to take a look at the demonstration
page.

A Basic Type-Ahead

The functionality core is similar to what Nicholas
C. Zakas presented at webreference.com
. Here is a simplified outline
of the javascript implementation. Cross-browser considerations and advanced
unobtrusive techniques are intentionally
left out
here, so be sure
to check out the final
implementation
for a complete view of the code.

Creating an array of suggestions

var suggestions = ["deleting spam","attending meeting", "writing status report", "debugging code"];

Getting a reference on the task input field

var taskInput = document.getElementById('taskInput');

Capturing the key press event

taskInput.onkeyup = function (evt) {
if(evt.keyCode == 8 ) return; // no type-ahead on backspace

Finding a match in the suggestions array

for (var i=0; i < suggestions.length && suggestions[i].toLowerCase().indexOf(taskInput.value.toLowerCase()) != 0; i++);
if(suggestions[i]) {

Replacing the user input with the suggestion

var userInputLength = self.inputElement.value.length;
taskInput.value= suggestions[i];

And finally, selecting the added text

taskInput.setSelectionRange(userInputLength,suggestions[i].length);
}
}

Adding the Ajax Touch

Querying a suggestion service

We are going to load the suggestion array using an asynchronous call to
a ’suggestion service’ hosted on the server. The idea is to keep the
array short and accurate by querying the server whenever we fall short of
suggestions matching the user’s input.

if (!suggestionsArray[i]) {
var HTTPReq = new XMLHttpRequest();
HTTPReq.onreadystatechange = function() {
suggestions = HTTPReq.responseText.split("&");
}
HTTPReq.open("GET", typeAheadServiceURL + "?inputid="+encodeURIComponent("taskInput")+"&inputtxt="+encodeURIComponent(taskInput.value),true);
HTTPReq.send(null);
}

We are passing two values to the suggestion service: the name of the input
field, and the user input. The service responds with a list of suggestions
(separated by the ampersand ‘&’ character).

Feeding the suggestion service

Now, we want our suggestion service to learn from our user input, so whenever
the form is submitted we do a second call to the service, this time
using the ‘POST’ method.

var HTTPReqPost = new XMLHttpRequest();
HTTPReqPost.onreadystatechange = self.populateSuggestions;
HTTPReqPost.open("POST", self.typeAheadServiceURL, true);
HTTPReqPost.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
HTTPReqPost.send("inputid="+encodeURIComponent('taskInput')+"&inputtxt="+encodeURIComponent(taskInput.value));

 

The Suggestion Service will be presented in the next article. In the meantime
you can play around with the demo page and share your thoughts.

Update: The Type-Ahead functionality now includes a drop-down list of suggestions (’google-suggest’-type).

Update (7/29/2005): A newer version of the script is available.

17 Responses to “Ajax Makeover: Adding a Smart Type Ahead”

  1. Steve Says:

    This looks pretty nice … although to be honest, I’ve always hated the UI of this type of autocomplete. It makes it very difficult to enter something that’s a substring of something that’s autocompleted … it can “surprise” you by suddenly changing the input to something else.

    What works for me better is a google-style autocomplete, with a dropdown that you can select from.

  2. cedsav Says:

    Good point Steve… On the other hand switching from typing text to selecting in a list also slows you down.

    I think it comes down to: do you know what you want to type ? or do you want to get several suggestions first ?

    The Type-Ahead works best in the first case. Sure, if you need a substring of the auto-completed text, you need to write it all and hit delete, but eventually the system will learn which one you use more often and auto-complete with it.

  3. cedsav Says:

    Well Steve, after all I went ahead and implemented the complete ‘google suggest’ experience… Check out the demonstration page.

  4. Bruce Boughton Says:

    The new suggest UI implementation is much better. One thing: now you have to use the mouse. Google’s implementation allows you to use the up/down keys to traverse the selections and the enter to key to select it. However, this should ideally be added in addition to what you already have.

    One other advantage your implementation currently has is that it doesn’t interfere with copying and pasting, which I find Google’s implementation does. (You cannot copy into a field — doing so clears the field’s value)

  5. cedsav Says:

    Bruce, I did implement the up & down keys… It should work fine with Firefox and IE. I haven’t tested with Safari and Opera 8 yet. What browser where you using ?

  6. Enrico Says:

    One bug:
    It doesn’t look like you show the updated choice list if someone types backspace.
    In other words, the selection doesn’t grow as the user is removing letters that otherwise would narrow it down to a smaler set…

  7. cedsav Says:

    Thanks Enrico.. I’ll fix that asap.

  8. cedsav Says:

    Alright, the backspace and delete keys now reloads the suggestion list.

  9. Bruce Boughton Says:

    Hmm. It appears to work just fine! Must have been user error before! Lol. Great implementation ;)

  10. Abraham Elias Says:

    I noticed that pressing enter “resets” the field, is this the correct functionality or should it fill the field with the currently selected value.

    For example press “a” attending meetings will come up. Since this is the correct suggestion I press enter. It then resets the field to “”. I think it should fill the field with “attending mettings” instead of reseting its value. Your thoughts?

    Using Firefox 1.0.4 in WinXP

  11. cedsav Says:

    Abraham.. pressing enter submits the form (which is the normal behavior). It looks like it is being reset, but it just reloads the form… it’s obviously bad usability design.. I’ll try to fix that asap.

  12. Abraham Elias Says:

    Cedric, Thanks for the quick response. I love what you are doing here, I think its great stuff. I think having it bubble up to submit the form is not a great idea. The user might have other fields to complete.

    Take a look at this example: http://wick.sourceforge.net/wick_sample/ (ajaxish as well)

    I’ve used the more traditional jsrs drop down.. http://www.ashleyit.com/rs/jsrs/select/php/select.php and seems to work well.

  13. Thierry Leveque Says:

    Good work Abraham!
    It is almost what I was looking for. The only thing missing is a down arrow button, that will display the full list. If we want to use it as a regular drop down list. If we don’t know what is inside the list.
    And maybe scrolling bar when the list is bigger than a maximum size….

  14. Nelson Says:

    Hello,
    I’ve been pulling my hair out trying to get a working demo of the Smart Type Ahead code. Do you have an HTML/PHP page that uses the new code from 7/29/05?
    Thank you!
    Nelson

  15. cedsav Says:

    Nelson, the updated code samples are listed in this post.
    If you can pinpoint the problem, email me at cedric at formassembly dot com.

  16. tendai Says:

    How do you use autocomplete with an existing menu so that the user instead of scrolling down enters text which is then interpreted from the existing menu and suggestions are provided based on the menu.

  17. Mary Says:

    unable to view either the demo or the code………