The complete steps required to build an AutoComplete Textbox
control are elaborated below.
Exposing a Web Service method to be invoked from Client
Side
The following is a partial code snippet for a web service
class definition.
Listing 1
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class myServices : System.Web.Services.WebService {
In order to expose the class, "myServices" to be
invoked from a client side, all we have to do is insert the following attribute
above the class definition.
Listing 2
[System.Web.Script.Services.ScriptService()]
By adding the above line, the AJAX run time extensions will
know that we are going to invoke the methods in the myServices class which is
going to be invoked from the client side.
Now the methods defined in the myServices class web service
are ready to be invoked from the client side. Let us pay some attention to how
we can invoke the methods from client side using AJAX.
Invoking the web service method using AJAX
Any AJAX enabled web page should at least have one
ScriptManager tag. One of the collections for this ScriptManager tag is the
Services collection. Through this Services collection, we can refer to the asmx
file that we are going to invoke. Now allow me to show the syntax for the
Services collection.
Listing 3
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="myServices.asmx" />
</Services>
</asp:ScriptManager>
Using the above code, we can invoke the methods defined in
the myServices.asmx from client side.
JavaScript code to invoke a Web Service method
Listing 4
ret = className.methodName(Parameter1, OnComplete, OnError, OnTimeOut);
The above is the syntax to invoke a Web Service method from
client side JavaScript code. Parameter1 is the parameter for the method.
OnComplete, OnError and OnTimeOut are client side JavaScript function names.
For example, the client side function "OnComplete" will be invoked
once the asynchronous call to the web service method completes successfully.
The function "OnError" will be invoked if the asynchronous call to
the method results in any error. And finally, the client side function "OnTimeOut"
will be invoked, if the asynchronous call to the method does not complete after
a certain timeout. These three functions are user defined functions. So, you
can name them to your wish. These functions will look as follows:
Listing 5
function OnComplete(arg)
{
alert (arg);
}
function OnTimeOut(arg)
{
alert("TimeOut encountered");
}
function OnError(arg)
{
alert("Error : " + arg);
}
How does an AutoComplete Textbox works?
Now, using the above technique, let us see how we can
implement an AutoComplete Textbox. To begin with, the web service method should
receive a parameter. This parameter will be the textbox content that the user
will be typing in. The web method can compare against a dictionary of words
that matches with the passed in parameter. When I say dictionary, it can be an
ArrayList or a database call to get the list of matching words. This can be
implemented according to your business logic. For our discussion we will use an
ArrayList which holds the possible combination of words. For better
performance, a binary search will be performed against the Array. .NET
Framework has an inbuilt method called BinarySearch. The only pre-condition to
use this method is that the Array should be sorted. Again, we can use the
inbuilt Sort method before invoking the BinarySearch method. The web service
method will return the closest match for the passed in parameter.
The JavaScript "OnComplete" function will receive
the text returned by the web service method. Once we have the text, all we have
to do is to assign the text to the Textbox. To simplify, the above discussion
can be summarized as follows:
1.
User types in text to the textbox.
2.
The "onkeyup" event for the textbox will fire a client side
JavaScript function.
3.
The JavaScript function will invoke the web service method. The typed in
text will be passed as a parameter to the web service method.
4.
The web service method will return the closest match for the passed in
text.
5.
The JavaScript "OnComplete" function will receive the value
returned by the web service method and assign it back to the Textbox.
Selecting the text inside the AutoComplete Textbox
One of the cosmetic features of an AutoComplete Textbox is
to select the text in the Textbox. For example, if the value returned by the
web service method is "hello," then we have to select the text "hello"
inside the Textbox. This can be performed by the following code.
Listing 6
function SelectText(intStart, intLength)
{
var myElement = document.getElementById('txtSearch');
// get reference to the Textbox
if (myElement.createTextRange)
// If IE
{
var myRange = myElement.createTextRange();
myRange.moveStart("character", intStart);
myRange.moveEnd("character", intLength - myElement.value.length);
myRange.select();
}
else if (myElement.setSelectionRange)
// if FireFox
{
myElement.setSelectionRange(intStart, intLength);
}
myElement.focus();
}
Invoking the Web Service method only when specific keys
are pressed
In order to make the AutoComplete Textbox more user
friendly, we should not invoke the web service method for any keys pressed. For
example, if the user presses the Backspace, we should invoke the web service
method. If we allow, then the user will never be able to delete any text that
he/she types in to the Textbox. Key trapping is a very simple process in JavaScript.
Using the following line we can capture the ASCII value of the key pressed.
Listing 7
Once we have the ASCII value, we can control which keys
should be allowed. Here is a code snippet which performs what we discussed in
this section.
Listing 8
intKeyCode = event.keyCode;
// See if a valid key key is pressed such as 0-9, A-Z, a-z, Hyphen, Underscore
if (((intKeyCode >= 48) && (intKeyCode <= 57)) || // Numbers 0-9
((intKeyCode >= 65) && (intKeyCode <= 90)) || // Upper case A-Z
((intKeyCode >= 97) && (intKeyCode <= 122)) || // Lower case a-z
(intKeyCode == 189))
// Hyphen
{
txtSearch = document.getElementById('txtSearch').value;
strOldText = txtSearch;
ret = myServices.WhatIsNext(txtSearch, OnComplete, OnError, OnTimeOut);
return (true);
}
else
// return false.
return (false);
Web Service method which finds the closest match
Here is the code snippet for the web service method which
searches for the closest match for the typed in text.
Listing 9
[WebMethod]public string WhatIsNext(string strText)
{
int intIndex;
string strWord;
strWord = strText;
intIndex = Array.BinarySearch(arrItems, strText);
// if an exact match is found
if (intIndex >= 0)
{
// if an Exact match is found, check the next item in the
// dictionary to see if it matches
if (arrItems[intIndex + 1].Length >= strText.Length)
{
if (arrItems[intIndex + 1].Substring(0, strText.Length).ToLower() ==
strText.ToLower())
{
strWord = arrItems[intIndex + 1];
}
else
{
strWord = arrItems[intIndex];
}
}
else
{}
}
else
{
if ((~intIndex) < (arrItems.Length))
{
// when we return the next word, make sure that it is really a closest match
if (arrItems[~intIndex].Length >= strText.Length)
{
if (arrItems[~intIndex].Substring(0, strText.Length).ToLower() ==
strText.ToLower())
{
strWord = arrItems[~intIndex];
}
else
{}
}
else
{}
}
}
return strWord;
}