Introduction
I have created a ComboBox
control that mimics the functionality of Google suggest.
As you type a search phrase, it automatically displays a list of matching entries in a dropdown without any postback.
See the picture below displaying matching moves with the ComboBox
Control.
Using the Code
I have used five files to make this project:
- A user control ComboBox.ascx - It contains one
textb<code>
ox to enter and listbox
to display result. - A JavaScript file AjaxCallBack.js - Used to request and get response data from server
- A default.aspx to display the user control - It asks for input and displays the result
- A frmRemote.aspx - It gets data from the server and sends filtered result to the caller
- An EmployeeList.xml - It contains the list of employees
Whenever we press a key in the textbox
, on onkeyup
event, a getResult()
function is called.
That calls a FillCombo()
function that sends a request to the server and gets a response.
Here is the JavaScript to make a call and get a response from the server.
var XMLHttp;
var requestURL = 'http://localhost:1455/AjaxComboBox/frmRemote.aspx?SearchText=';
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)||
(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
var count=0;
var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;
var _Combo;
function FillCombo(combo,txt)
{
_Combo=combo;
var url = requestURL + txt ;
XMLHttp = GetXmlHttpObject(stateChangeHandler);
XMLHttp.open('GET',url,true);
XMLHttp.send(null);
}
function GetXmlHttpObject(handler)
{
var objXmlHttp = null;
if (is_ie)
{
var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';
try
{
objXmlHttp = new ActiveXObject(strObjName);
objXmlHttp.onreadystatechange = handler;
}
catch(e)
{
alert('IE detected, but object could not be created.
Verify that active scripting and activeX controls are enabled');
return;
}
}
else if (is_opera)
{
alert('Opera detected. The page may not behave as expected.');
return;
}
else
{
objXmlHttp = new XMLHttpRequest();
objXmlHttp.onload = handler;
objXmlHttp.onerror = handler;
}
return objXmlHttp;
}
function stateChangeHandler()
{
if(XMLHttp.readyState==4 || XMLHttp.readyState == 'complete')
{
var str = XMLHttp.responseText;
if (XMLHttp.responseXML.documentElement != null)
{
FillComboBox_Blur(XMLHttp.responseXML.documentElement);
}
else
{
alert("No Match");
}
}
}
function FillComboBox_Blur(Node)
{
var NodeList;
NodeList = _Combo;
var TextNodeList = Node.getElementsByTagName('Text');
var IdNodeList = Node.getElementsByTagName('Id');
var textName;
var valueName;
for (var count = NodeList.options.length-1; count >-1; count--)
{
NodeList.options[count] = null;
}
for (var count = 0; count < TextNodeList.length; count++)
{
textName = GetInnerText(TextNodeList[count]);
valueName = GetInnerText(IdNodeList[count]);
TempOption = new Option( textName, valueName, false, false);
NodeList.options[NodeList.length] = TempOption;
NodeList.size= NodeList.options.length;
NodeList.style.display='block';
}
if(TextNodeList.length==0)
{
NodeList.style.display='none';
}
}
function GetInnerText (node)
{
return (node.textContent || node.innerText || node.text) ;
}
A call from the JavaScript is made to the server. On the server, there is a file frmRemote.aspx, that retrieves the result from the XML file, filters it and sends the resultant data as response.
if (Request["SearchText"] != null)
{
string SearchText = Request["SearchText"].ToString();
int count = 0;
string strXmlNames = "";
if (SearchText != "")
{
XPathDocument xDoc = new XPathDocument(System.Web.HttpContext.
Current.Request.PhysicalApplicationPath + "EmployeeList.xml");
XPathNavigator xNav = xDoc.CreateNavigator();
XPathExpression strExpression = xNav.Compile("Employee/EmpName");
XPathNodeIterator xIterator = xNav.Select(strExpression);
while (xIterator.MoveNext())
{
XPathNavigator nav = xIterator.Current.Clone();
if (nav.Value.Trim().StartsWith(SearchText, true, null))
{
strXmlNames += "<element><Text>" + nav.Value +
"</Text> <Id>" + nav.Value + "</Id></element>";
count++;
}
}
}
if(count>0)
strXmlNames += "<element><Text>" + "Total search result: " +
count + "</Text> <Id>" + count + "</Id></element>";
strXmlNames = "<?xml version=\"1.0\" ?><Records>" + strXmlNames +
"</Records>";
Response.Clear();
Response.ContentType = "text/xml";
Response.Write(strXmlNames);
Response.End();
}
Point of Interest
The amazing thing about this control is that every time you enter a letter into the search box, an AJAX call is performed to retrieve a list of matching results from the server.
History
- 5th November, 2008: Initial post