Introduction
In the quest to build the next big user-driven web application, very good developers often tend to brush a number of features under the carpet, often classifying them as irrelevant. Unfortunately, when you have two or more web communities that essentially do the same thing, as is often the case these days, it's the little things that will determine which website secures a more dedicated user base.
Background
A field used for retrieving phone numbers in a form is one of those, not-crucial-to-the-mission, yet effective ways of making life easier for your site's visitors, even if by an iota. Throughout my development experience, I have been unable to leave users who enter phone or fax number into my sites by manually tabbing their way through three fields at a time. The JavaScript code required for achieving auto-tab functionality in phone fields is simple enough, so is manually attaching it to your ASP.NET TextBox
server controls. However, true nirvana is only achieved by combining both the JavaScript and the ASP.NET TextBox
es into a reusable server control.
Using the code
The CSGControls.PhoneField
is one solution to the auto-tabbed phone field control problem. You can use it in your web application by downloading the code attached to this article. Add the control to your toolbox by right-clicking in your toolbox area in the design view, clicking Add/Remove Items, and browsing to the location of the control's DLL.
The phone field control is not a bulky control and comes with but a handful of properties that allow it to achieve its purpose. Below are some of the properties.
Property |
Description |
formattedText : string |
Returns a formatted version of the phone value, according to the label separators you specify, default is (xxx) xxx-xxxx |
EnableClientScript : bool |
Provides an option of adding the phone field to your site without the default JavaScript at runtime. |
The JavaScript code that controls the magic is first assigned to a local variable in the server control class and then rendered to the browser at runtime. Below is a glimpse of the JavaScript:
protected const string MOVE_FOCUS_SCRIPT = @"
...
function __Move_Focus(obj,evt,len,next_field)
{
var phone_field_length
if (evt == 'down') {
phone_field_length=obj.value.length;
}
else if (evt == 'up')
{
if (obj.value.length != phone_field_length)
{
phone_field_length=obj.value.length;
if (phone_field_length == len)
{
document.getElementById(next_field).focus();
}
}
}
}
...
";
The above code essentially tracks keystrokes in each field. The fields are all allocated a maximum number of characters they can contain. After every keystroke, a check is made to detect whether the maximum number of characters assigned to each field has been reached. If the maximum has indeed been reached, then the script moves focus to the next field where applicable.
The script is added to the browser in the OnPreRender
event of the control's life-cycle as in the code snippet below.
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender (e);
string typename = typeof(PhoneField).ToString().Replace(".","_");
DetermineRenderClientScript();
if (renderClientScript)
{
if(!Page.IsClientScriptBlockRegistered(typename))
{
Page.RegisterClientScriptBlock(typename,MOVE_FOCUS_SCRIPT);
}
}
}
On the first and the second fields of our phone field control, we add event handlers for the "onKeyUp
" and "onKeyDown
" events. Our onKeyDown
event updates the character count for the field in question, and our onKeyUp
event compares it to the maximum allowable characters and moves the cursor over to the next field where necessary.
...
_field2.Attributes.Add("onKeyUp", MOVE_FOCUS_FUNC +
"(this,\'up\',3,\'"+(this.UniqueID +
"_" + _field3.ClientID)+"\')");
_field2.Attributes.Add("onKeyDown", MOVE_FOCUS_FUNC +
"(this,\'down\',3)");
...
Possible enhancements
Although I have made accommodations for a string format, e.g., "{0} {1}-{2}" to be used, I'm not making optimal use of it. Ideally, a flag can be used to determine whether to use a format string property to format the text fields, or allow a user to assign the formatting strings via individual properties, as is currently the case in my example.
Happy coding!