Article
Make Life Easy With Autocomplete Textboxes
The very last part of this function is to set the focus to the textbox so that when a user types, it will replace the selected text:
function textboxSelect (oTextbox, iStart, iEnd) {
switch(arguments.length) {
case 1:
oTextbox.select();
break;
case 2:
iEnd = oTextbox.value.length;
/* falls through */
case 3:
if (isIE) {
var oRange = oTextbox.createTextRange();
oRange.moveStart("character", iStart);
oRange.moveEnd("character", -oTextbox.value.length + iEnd);
oRange.select();
} else if (isMoz){
oTextbox.setSelectionRange(iStart, iEnd);
}
}
oTextbox.focus();
}
Replacing the Textbox Selection
Another task we’ll need to be able to do is to replace the currently selected text with some other text. For this, we will create the textboxReplaceSelect() method, which will take two parameters: the textbox to act on, and the text to insert. Because we will use ranges, we’ll need to create different code for IE and Mozilla. First, let’s take a look at the IE code:
function textboxReplaceSelect (oTextbox, sText) {
if (isIE) {
var oRange = document.selection.createRange();
oRange.text = sText;
oRange.collapse(true);
oRange.select();
} else if (isMoz) {
...
}
oTextbox.focus();
}
On line 4, we create a range from the document’s current selection (which we can safely assume is within the textbox, as this will be called on the keypress event of the textbox). On the following line, we replace the range’s text with the given string. On line 6, we call the range’s collapse() method, which sets the length of the range to 0; the parameter, a Boolean, collapses to the end of the range if the value is true, and collapses to the beginning of the range if the value is false. Finally, we select the collapsed range, which places the cursor after the text we just inserted.
In Mozilla, we can achieve the same effect with some simple string manipulation. We can determine the start and end points of the selection by using the Mozilla selectionStart and selectionEnd attributes of a textbox:
function textboxReplaceSelect (oTextbox, sText) {
if (isIE) {
var oRange = document.selection.createRange();
oRange.text = sText;
oRange.collapse(true);
oRange.select();
} else if (isMoz) {
var iStart = oTextbox.selectionStart;
oTextbox.value = oTextbox.value.substring(0, iStart) + sText + oTextbox.value.substring(oTextbox.selectionEnd, oTextbox.value.length);
oTextbox.setSelectionRange(iStart + sText.length, iStart + sText.length);
}
oTextbox.focus();
}
On line 9, we are just saving the starting point of the textbox selection; we’ll need it later. Line 10 looks complicated, but in reality it just takes the string prior to the selection and the string after the selection, and adds sText between them. After that, we just need to replicate what we did in IE: set the cursor to appear after the text that was just inserted. So, on line 11, we set the selection range to be the old starting point plus the length of the text that was inserted. This effectively copies what we did for IE.
Matching
The next step in the process is to write a method that will search an array of strings and return the first value that begins with a given string (for example, we need to pass in “a” and have it return the first value in the array that begins with the letter “a”). This method will be called autocompleteMatch() and will take two parameters: the text to match and the array of values to match against.
The search is straightforward -- we just iterate through the array and check each value. If the method returns true, then we return the value. If no matches are found, a null value is returned. Here’s the full code:
function autocompleteMatch (sText, arrValues) {
for (var i=0; i < arrValues.length; i++) {
if (arrValues[i].indexOf(sText) == 0) {
return arrValues[i];
}
}
return null;
}
Note that for this to work correctly, the strings in arrValues must be in alphabetical order.
The Guts
With our other methods built, we can move into the guts of the autocomplete textbox: the autocomplete() method. This method will take three parameters: the textbox to act on, the event object, and an array of possible values. Assuming that we have an array called arrValues, the call would look like this:
<input type=”text” onkeypress=”return autocomplete(this, event, arrValues)” />
We will be looking at the keycode of the pressed key first:
function autocomplete(oTextbox, oEvent, arrValues) {
switch (oEvent.keyCode) {
...
}
}
Note that we still format the event object using our EventUtil.formatEvent() method.
There are several keys that we don’t want to interfere with, such as the cursor keys; we’ll just return true in these special cases:
function autocomplete(oTextbox, oEvent, arrValues) {
switch (oEvent.keyCode) {
case 38: //up arrow
case 40: //down arrow
case 37: //left arrow
case 39: //right arrow
case 33: //page up
case 34: //page down
case 36: //home
case 35: //end
case 13: //enter
case 9: //tab
case 27: //esc
case 16: //shift
case 17: //ctrl
case 18: //alt
case 20: //caps lock
case 8: //backspace
case 46: //delete
return true;
break;
...
}
}
Next, we’ll take the default case: when the user types a character. In this case we need to complete a number of steps:
- We must replace the selected text with the character the user typed
- We must try to get a match to the text the user has typed in
- If found, we must set the textbox to the suggested text and set the selection to encompass only the letters that the user did not type
This may sound complicated, but the helper functions we’ve already written will make it much easier.