How to Create an Ajax Autocomplete Text Field: Part 10 [con't]
Both the up and down arrow key handlers call the scrollList()
method to display the newly highlightedRow
. Once one iterates through the visible list items, there comes a point where the highlightedRow
would be out of sight. After all, the reason a scrollbar is displayed is because there are too many items in the list to view. If the user couldn't see the currently selected item, using the arrow keys could become a frustrating experience!
The highlightedRow
is stored in a local variable to avoid successive function calls and tested for validity; basically any non-null value will do. The second if
statement uses two DOM properties that we haven't seen yet. The offsetTop
is a read-only property that stores the vertical offset position of the current element relative to its offset container. The <body>
is the offset container for statically-positioned (default) elements, but positioned elements create their own offset container space. For this reason, the row's offsetTop
returns the top
of the row's distance from the top
of the container. The scrollTop
returns the distance between the top
edge of the element and its top
edge currently in view. The expression highlightedRow.offsetTop evaluates to
true
if the top
of the row has gone past the top
of the container. Setting the container's scrollTop
value equal to the row's offsetTop
has the effect of moving the scrollbar until the highlightedRow
is fully in view at the top
of the viewport.
To scroll down, we need to calculate the rowOffsetBottom
by adding the row's clientHeight
to its offsetTop
since there's no "offsetBottom" property. To ascertain if we need to scroll the list, we can compare the rowOffsetBottom
to the container's scrollTop
plus its clientHeight
(essentially its "scrollBottom"). A rowOffsetBottom
larger than the container's scrollTop
plus its clientHeight
indicates that the list requires some scrolling to bring the highlightedRow
into view. In this case, setting the container's scrollTop
to the rowOffsetBottom
minus the highlightedRow
's clientHeight
moves the scrollbar until the highlightedRow
is fully in view at the bottom of the viewport:
getHighlightedRow()
function is getter method at its most basic. Here's the code:
Add the above methods to the return object to make them publicly accessible:
Figure 1 illustrates the various HTMLElement properties that can be used to calculate scrollbar positioning.
Update the handleMouseEvent()
Function
The handleMouseEvent()
function must now be updated to use the new RowManager
class because it includes functionality which is independent from the RowManager
. It's possible to highlight two rows simultaneously by using the mouse in conjunction with the arrow keys. Who would do such a thing? No one under normal circumstances, but it's possible to leave the mouse in a position where it happens to hover over a list item. In such an instance it would be confusing to the user as to which row is actually selected, as Figure 2 demonstrates.
Here's the handleMouseEvent()
function updated to call the RowManager
's methods:
The commented last line has been replaced by two calls to the RowManager
class. The first call sets the row's style to popupRow
followed by the event type
, which include over
, up
, down
and out
. The next line sets the highlightedRow
to null on the mouseout
event because it's the only event for which the current row should not be set as the current one.
Here's the file with this week's updates.
Next week, we'll wrap up the Autocomplete Control series by covering the rest of the control keys, including TAB
and ENTER
. As you'll discover, these keys have to be handled differently than the ones we've covered thus far. We'll also look at how to close the list when the user clicks elsewhere on the page.
References
- Tutorial on Increment and Decrement Operators
- Strict Equality Operators article on WebReference
- DOM Element Properties (including scrollTop and offsetTop)
- Key Events Tutorial
Original: July 16, 2008