| home / programming / javascript / ncz / column2 / 1 | [previous] [next] |
|
|
Remember the autosuggest() method from the last
article? To implement the dropdown list of suggestions it's necessary to
update this method.
The first update is the addition of a second argument which indicates whether
or not the type ahead functionality should be used (the reason why will be explained
shortly). Naturally, the typeAhead() method should only be called
if this argument is true. If there's at least one suggestion, type
ahead should be used and the dropdown list of suggestion should be displayed
by calling showSuggestions() and passing in the array of suggestions;
if there's no suggestions, the dropdown list should be hidden by calling hideSuggestions():
AutoSuggestControl.prototype.autosuggest = function (aSuggestions,
bTypeAhead) {
if (aSuggestions.length > 0) {
if (bTypeAhead) {
this.typeAhead(aSuggestions[0]);
}
this.showSuggestions(aSuggestions);
} else {
this.hideSuggestions();
}
};
You will also remember that this method is called from the suggestion provider's
requestionSuggestions() method, which means it too must be updated.
This is a fairly easy update; you need only add a second argument and then pass
it back into the autosuggest() method when it's called:
StateSuggestions.prototype.requestSuggestions = function (oAutoSuggestControl,
bTypeAhead) {
var aSuggestions = [];
var sTextboxValue = oAutoSuggestControl.textbox.value;
if (sTextboxValue.length > 0){
for (var i=0; i < this.states.length;
i++) {
if (this.states[i].indexOf(sTextboxValue)
== 0) {
aSuggestions.push(this.states[i]);
}
}
}
oAutoSuggestControl.autosuggest(aSuggestions,
bTypeAhead);
};
With both of these methods updated, it's now necessary to update the handleKeyUp()
method. First, just add the second argument (true) when calling requestSuggestions():
AutoSuggestControl.prototype.handleKeyUp = function (oEvent) {
var iKeyCode = oEvent.keyCode;
if (iKeyCode < 32 || (iKeyCode >=
33 && iKeyCode <= 46) || (iKeyCode >= 112 && iKeyCode
<= 123)) {
//ignore
} else {
this.provider.requestSuggestions(this,
true);
}
};
This functionality now works exactly as it did previously, but there are a
couple of other keys that require special attention: Backspace and Delete. When
either of these keys are pressed, you don't want to activate the type ahead
functionality because it will disrupt the process of removing characters from
the textbox, but there's no reason not to show the dropdown list of suggestions.
For the Backspace (key code of 8) and Delete (key code of 46) keys, you can
also call requestSuggestions(), but this time, pass in false
to indicate that type ahead should not occur:
AutoSuggestControl.prototype.handleKeyUp = function (oEvent) {
var iKeyCode = oEvent.keyCode;
if (iKeyCode == 8 || iKeyCode == 46) {
this.provider.requestSuggestions(this,
false);
} else if (iKeyCode < 32 || (iKeyCode >= 33
&& iKeyCode <= 46) || (iKeyCode >= 112 && iKeyCode <=
123)) {
//ignore
} else {
this.provider.requestSuggestions(this,
true);
}
};
Now when the user is removing characters, suggestions will still be provided and the user can click on one of them to select the value for the textbox. This is acceptable, but to really be usable the autosuggest control needs to respond to keyboard controls.
The desired keyboard functionality revolves around three keys: the up arrow, the down arrow and Enter (or Return). When the dropdown suggestion list is displayed, you should be able to press the down arrow to highlight to the first suggestion, then press it again to move to the second, and so on. The up arrow should then be used to move back up the list of suggestions. As each suggestion is highlighted, the value must be placed in the textbox. When the Enter key is pressed, the suggestions should be hidden, leaving the last suggestion to be highlighted in the textbox.
When the user scrolls through the suggestions in the list, you must know which
suggestion is current. To do this, a property must be added to the AutoSuggestControl
definition as follows:
function AutoSuggestControl(oTextbox, oProvider) {
this.cur = -1;
this.layer = null;
this.provider = oProvider;
this.textbox = oTextbox;
this.init();
}
The cur property stores the index of the current suggestion in
the suggestions array. By default, this is set to -1 because this there are
no suggestions initially.
When the down arrow key is pressed, the next suggestion in the dropdown list
should be highlighted. To encapsulate this functionality, a method named nextSuggestion()
will be added. Here's the code:
AutoSuggestControl.prototype.nextSuggestion = function () {
var cSuggestionNodes = this.layer.childNodes;
if (cSuggestionNodes.length > 0 && this.cur
< cSuggestionNodes.length-1) {
var oNode = cSuggestionNodes[++this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
}
};
This method obtains the collection of child nodes in the dropdown layer. Since
only the <div/> elements containing the suggestions are child
nodes of the layer, the number of child nodes accurately matches the number
of suggestions. This number can be used to determine if there are any suggestions
(in which case it will be greater than 0) and also if there is a next suggestion
(which means that it's greater than cur). To ensure that cur
never points to an empty node, it must never be allowed to be larger than the
number of child nodes minus 1 (because the last element in a collection with
n elements is n-1).
If it these two tests are passed, then cur is incremented and
the child node in that position is retrieved and stored in oNode.
Next, the node is passed in to highlightSuggestion(), which highlights
it and unhighlights the previously highlighted suggestion. From there, the value
of the textbox is once again set to the text contained inside of the <div/>.
As you may have suspected, another method to highlight the previous suggestion is also necessary. Here it is:
AutoSuggestControl.prototype.previousSuggestion = function () {
var cSuggestionNodes = this.layer.childNodes;
if (cSuggestionNodes.length > 0 && this.cur
> 0) {
var oNode = cSuggestionNodes[--this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
}
};
The previousSuggestion() method is similar to nextSuggestion().
The main differences are that you need to ensure cur is greater
than 0 to proceed (you still must make sure that there are suggestions by checking
the number of child nodes in the dropdown layer) and that cur must
be decremented instead of incremented. Other than these two changes, the algorithm
is the same. Now back to the three keys.
| home / programming / javascript / ncz / column2 / 1 | [previous] [next] |
Created: March 27, 2003
Revised: April 08, 2005
URL: http://webreference.com/programming/javascript/ncz/column2/1