Introduction
When I was involved in a project which used many ASPX pages with DropDownList
s and ListBox
s for selecting persons, departments and etc., my customer asked me if he could type the characters on his keyboard and select the suitable item. And, I tried to make work easier for him. At first, it was only JavaScript code, and now it has ASP.NET server controls. So, I'd like to describe two ASP.NET server controls: xNetDropDownList
and xNetListBox
, with the possibility to move the focus to the first most suitable item on the list when a user types in characters on the keyboard.
Background
The principle of work for both components is similar; therefore, I will describe xNetDropDownList
. On a client-side element xNetDropDownList
is represented as an HTML <select>
box. When an element receives focus, a tooltip appears above it. The entered characters are represented in the Tooltip and the focus moves to the first suitable item on the list. Pressing Escape deletes all the entered characters and the focus is moved to the first item. The backspace key deletes the last entered character. The focus is moved to the item on the list, corresponding the text in the Tooltip after deleting the character. When an element loses focus, the tooltip disappears.
For correct working, the list of items must be sorted in ascending order!
Implementation
The component xNetDropDownList
is inherited from System.Web.UI.WebControls.DropDownList
. Several new properties were added to it. They are mainly used for setting visual parameters of the tooltip. These properties are described in the table:
Public property |
Type |
Description |
ToolTipHide |
bool |
Gets or sets the visibility of the tooltip; false to show the tooltip, true not to show. |
ToolTipBackColor |
Color |
Gets or sets the background color. |
ToolTipBorderColor |
Color |
Gets or sets the border color. |
ToolTipBorderStyle |
BorderStyle |
Gets or sets the border style. |
ToolTipBorderWidth |
Unit |
Gets or sets the border width. |
ToolTipFontFamily |
string |
Gets or sets an ordered array of font names. |
ToolTipFontSize |
FontUnit |
Gets or sets the font size. |
ToolTipFontBold |
bool |
Gets or sets a value that indicates whether the font is bold. |
ToolTipForeColor |
Color |
Gets or sets the color of the text. |
ToolTipOffsetLeft |
int |
Gets or sets horizontal moving of the left top point of the tooltip as the co-ordinate of the DropDownList or the ListBox . Measuring unit is a pixel. In the properties designer, just figures (integers) are typed in. |
ToolTipOffsetTop |
int |
Gets or sets vertical moving of the left top point of the tooltip as the co-ordinate of the DropDownList or ListBox . Measuring unit is a pixel. In the properties designer just figures (integers) are typed in. |
ToolTipPadding |
Unit |
Gets or sets the amount of space to insert between the text and the border. |
ToolTipInitialWidth |
Unit |
Gets or sets the initial width. |
ToolTipZIndex |
int |
Gets or sets the z-index. |
ToolTipSaveText |
bool |
Gets or sets saving the typed in text in the tooltip. If true , the typed in text is saved when the element loses focus and acquires focus again. If false , the typed in text is lost. |
This picture gives an explanation for the ToolTipOffsetLeft
and ToolTipOffsetTop
properties:
The functionality for searching a suitable item on the list is realized on the JavaScript.
The function xOnFocus()
is used for creating and setting properties for the tooltip. When a <select>
element receives focus the first time, a new HTML element <div>
is created; otherwise, the function controls the behavior of the tooltip with settings in the ToolTipSaveText
and ToolTipHide
properties.
function xOnFocus(elm)
{
var el = document.getElementById('div_' + elm.id);
if (!el)
{
var xdiv = document.createElement('DIV');
xdiv.id = 'div_' + elm.id;
xdiv.noWrap = true;
xdiv.style.position = 'absolute';
xdiv.ToolTipText = '';
xdiv.style.color = elm.ToolTipForeColor;
xdiv.style.width = elm.ToolTipInitialWidth;
xdiv.style.padding = elm.ToolTipPadding;
xdiv.style.display = (elm.ToolTipHide == 'false') ? 'inline' : 'none';
xdiv.style.backgroundColor = elm.ToolTipBackColor;
xdiv.style.borderColor = elm.ToolTipBorderColor;
xdiv.style.borderStyle = elm.ToolTipBorderStyle;
xdiv.style.borderWidth = elm.ToolTipBorderWidth;
xdiv.style.fontFamily = elm.ToolTipFontFamily;
xdiv.style.fontSize = elm.ToolTipFontSize;
xdiv.style.fontWeight = elm.ToolTipFontBold;
xdiv.style.zIndex = elm.ToolTipZIndex;
if (document.documentElement && document.documentElement.scrollTop)
xdiv.style.top = document.documentElement.scrollTop +
elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
else
xdiv.style.top = document.body.scrollTop +
elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
if (document.documentElement && document.documentElement.scrollLeft)
xdiv.style.left = document.documentElement.scrollLeft +
elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);
else
xdiv.style.left = document.body.scrollLeft +
elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);
elm.insertAdjacentElement('afterEnd', xdiv);
}
else
{
if (document.documentElement && document.documentElement.scrollTop)
el.style.top = document.documentElement.scrollTop +
elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
else
el.style.top = document.body.scrollTop +
elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
if (document.documentElement && document.documentElement.scrollLeft)
el.style.left = document.documentElement.scrollLeft +
elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);
else
el.style.left = document.body.scrollLeft +
elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);
if (elm.ToolTipSaveText == 'false')
{
el.innerText = '';
el.ToolTipText = '';
}
el.style.display = (elm.ToolTipHide == 'false') ? 'inline': 'none';
}
}
The function xOnBlur()
hides the tooltip:
function xOnBlur(elm)
{
var el = document.getElementById('div_' + elm.id);
if (el) el.style.display = 'none';
}
The function xOnKeyUp()
handles pressing the following keys: Esc, BackSpace, and Enter. Notice, if the property AutoPostBack
is true
, in addition to the standard behavior of the DropDownList
and ListBox
controls, an automatic postback to the server will occur when the user presses the Enter key.
function xOnKeyUp(key_event)
{
var lb = key_event.srcElement;
var el = document.getElementById('div_' + lb.id);
if (el)
{
if (key_event.keyCode == 8)
{
key_event.returnValue = false;
if (el.ToolTipText.length > 0)
el.ToolTipText =
el.ToolTipText.substr(0, el.ToolTipText.length - 1);
el.innerText = el.ToolTipText + ' ';
xFindItem(el.ToolTipText, lb);
}
if (key_event.keyCode == 27)
{
key_event.returnValue = false;
el.ToolTipText = '';
el.innerText = '';
xFindItem(el.ToolTipText, lb);
}
if (key_event.keyCode == 13)
{
key_event.returnValue = true;
if (lb.AutoPostBack == 'true') lb.onchange();
}
}
}
The function xOnKeyPress()
processes alphanumeric characters:
function xOnKeyPress(key_event)
{
var lb = key_event.srcElement;
var el = document.getElementById('div_' + lb.id);
if (el)
{
if (key_event.keyCode != 13)
{
el.ToolTipText = el.ToolTipText + String.fromCharCode(key_event.keyCode);
el.innerText = el.ToolTipText +' ';
xFindItem(el.ToolTipText, lb);
}
key_event.returnValue = false;
}
}
The function xFindItem()
is the main function, and it is responsible for searching an item on the list.
function xFindItem(s, lb)
{
s = s.toUpperCase();
var slen = s.length;
var lblen = lb.length;
var lbo = lb.options;
if (slen == 0 && lblen > 0)
{
lb.selectedIndex = 0;
return;
}
for (i = 0; i < lblen; i++)
{
if (lbo[i].text.toUpperCase().substr(0, slen) == s)
{
lb.selectedIndex = i;
break;
}
}
}
The components were tested in Internet Explorer version 6.0.
Using the code
You can use this control just like any other web server control.
Examples
There are three pages included in the demo project:
- Sample1.aspx -
xNetDropDownList
and xNetListBox
contains the list of the last and first names entered directly through the ListItem
Collection Editor. This page demonstrates the general work of the components.
- Sample2.aspx -
xNetDropDownList
and xNetListBox
are connected to the Northwind database (MS SQL Server). Remember to change the username and password in the connection string!
- Sample3.aspx – presents different variants of appearance.
- 10th Mar, 2006
- 12th Jun, 2006
- Press the Enter key issue was resolved.
- 18th Jun, 2006
- The same issue with tab key was corrected.
- 6th Aug, 2006
- The problem with setting properties through code was resolved.
- 15th Oct, 2006
- The issues with the position of the tooltip after window resize, and IE6 with
DOCTYPE
were fixed. Thanks to Ondra Jires.