Introduction
Auto-Completion is a very interesting feature that was primarily made popular by Google. I have already written a couple of articles that explain how to implement this feature. In this article, I will implement the auto-completion feature using ASP.NET 2.0 client callbacks.
Database design
I will be using the Northwind database, which is the default database for SQL SERVER 7 and SQL SERVER 2000.
Class diagram
I tried to keep the code organized and implemented different classes. Take a look at the class diagram below:
Explanation
- Product: The
Product
class is a simple entity class which exposes ProductName
as the public property. - ProductRepository:
ProductRepository
is responsible for performing the CRUD operations on the products. - CacheRepository:
CacheRepository
is used to hold the data into the HttpCache
object. This will prevent from unnecessary database access. - HTMLTableHelper: This class is responsible for creating the HTML table.
- DataAccess: The
DataAccess
class is used to access the database. - The GetProduct method: The
GetProduct
method is responsible for retrieving the products.
Let's check out the code:
public static IList<Product> GetProducts(string criteria)
{
string key = "Products_" + criteria[0];
IList<Product> list = CacheRepository.GetObjects<Product>(key);
if (list == null || list.Count == 0)
{
list = DataAccess.GetProducts(criteria);
CacheRepository.SaveObject(key, list);
}
List<Product> productList = list as List<Product>;
list = productList.FindAll(delegate(Product product)
{
return product.ProductName.ToLower().StartsWith(criteria.ToLower());
});
return list;
}
The GetProducts
method takes the string variable criteria
as an input parameter. After that, a key is generated that is based on the keyword Products
and the first character of criteria
. This means that if you type "C" then the generated key will be Products_C
. CacheRepository
uses the key to find the products in the cache. If the products are not found in the cache, then they are retrieved from the database. Otherwise, the matching products are returned from the cache. I have used the anonymous method to search for the matching items in the list.
list = productList.FindAll(delegate(Product product)
{
return product.ProductName.ToLower().StartsWith(criteria.ToLower());
});
CacheRepository simply saves and retrieves the items from the cache. Take a look at the two methods exposed by it:
public static IList<T> GetObjects<T>(string key)
{
IList<T> list = (IList<T>) HttpContext.Current.Cache[key];
return list;
}
public static void SaveObject(string key, object obj)
{
HttpContext.Current.Cache.Insert(key, obj);
}
Registering client callbacks
In order to use the ASP.NET 2.0 Client Callbacks feature, you will first need to register it. Take a look at the code below, which registers the client callbacks.
private void RegisterClientCallbacks()
{
string callbackRef = ClientScript.GetCallbackEventReference(this, "arg",
"RecieveServerData", "context");
string script = String.Empty;
if (!ClientScript.IsClientScriptBlockRegistered("CallServer"))
{
script = "function CallServer(arg,context) { " + callbackRef + "}";
ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer",
script, true);
}
}
Implementing the client script
Now, let's check out the client code that is used to trigger the server-side method. The callback method is fired when the user types some text in the textbox. The textbox onKeyDown
event is responsible for calling the server method.
Enter Search Text: <input type="text" onkeydown="return GetProducts(event)" id="txtSearch" name="txtSearch" />
The JavaScript GetProducts
function sends the request to the appropriate functions depending on the keystroke.
function GetProducts(e)
{
var keynum
var keychar
var numcheck
if(window.event) {
keynum = e.keyCode
}
else if(e.which) {
keynum = e.which
}
keychar = String.fromCharCode(keynum)
numcheck = /\d/
if(keynum == DOWN)
{
MoveCursorDown();
return;
}
else if(keynum == UP)
{
MoveCursorUp();
return;
}
else if(keynum == ENTER)
{
if(IsFireFox())
{
document.getElementById("txtSearch").value =
selectedRow.childNodes[1].innerHTML;
}
else
{
document.getElementById("txtSearch").value = selectedRow.innerText;
}
document.getElementById("results").innerHTML = '';
return false;
}
if(keynum != DOWN && keynum != UP && keynum >= 65 && keynum <= 90)
{
word = word + keychar;
}
else if(keynum == BACKSPACE)
{
word = word.substring(0,word.length-1);
}
CallServer(word,'');
}
Let's check out the MoveCursorDown
function, which is fired when the user presses the down arrow key from the keyboard.
function MoveCursorDown()
{
selectedRow = null;
table = document.getElementById("MyTable");
if(table == null) return;
rows = table.getElementsByTagName("TR");
if(index < rows.length)
{
if(index < rows.length -1)
{
index++;
SetDefaultRowColor();
selectedRow = rows[index];
selectedRow.className = 'HighlightRow';
}
}
}
As you can see in the above code, first I check if the index is less than the total number of rows minus 1. If that is the case, then the selectedRow
is highlighted with a different color. Take a look at the screenshot below:
There is a lot more JavaScript code used in this demo. All of the code is available for download at the top of this article.
Similar articles
Conclusion
Auto-completion is a very handy feature for any website. It gives users the ability to search thousands of records without iterating through them incrementally.
History
- 15 June, 2007 -- Original version posted