
Looking for the VB.NET Version? Click Here
Latest Features without the Latest Features?
As the web world introduces new styles and features, it is becoming more and more demanding for us developers.
Customers/clients along with managers and directors want the latest features without the latest features. Confused by this?
So was I. You'll understand by the end of this article what that statement exactly means and how you probably face it everyday.
What Started it All
A few weeks ago, I had to implement a new project. It was dealing with your typical requirements of fetching data and
presenting reports. It was pretty basic (or so I thought) and simple in the beginning. I ended up on a section, where I had a
simple grid representing some data. Here I had to implement a search feature based on a couple of their fields, which they
wished to type in. It couldn't be drop down lists because they had over a few thousands (5+) various types of choices. It
would just take way too long to load all those items. To make it worse they had 6 different criteria's to search from being
able to mix and match.
For the first client demo, I ended up putting 6 different textbox's, where the client can type between any of them, and get the
result they wanted. To make it more friendly, I allowed like searches so they wouldn't even have to type the entire words of
say company names, or addresses, etc... They loved this feature, but it would definately get me into more trouble.
The management team had a meeting with the customers, and next thing I knew, I was fluttered with requests that each search
type should allow auto suggestions. Now to make it a bit complicated, I had about 6 different textbox's (Isn't that a PAIN.)
and to have all of them having auto suggestions looking at different sources was just annoying. But what can I do, I loaded the
AJAX framework, and quickly made this possible using some guidelines from http://asp.net/ajax/downloads/. We went off to
do another demo, and they loved it. So what was wrong?
Requirements Does Not Meet
Well as my luck would turn out, for some policy reason of the unnamed organization, we would not be allowed to use the
AJAX framework on the server? Why you may ask? Isn't it silly? Well all I can say, was it was not something coming from
me, but something we all face and do, that is compromise even though it is not logical.
So, I set off to make my own auto suggest, using as limited code as possible, using the asynchonous calls the old fasioned
way without the frameworks. For this example, I will show you how to do this, using a more basic case, allowing you to evolve
it as much as you wish.
What Is Needed?
All that is needed is two pages:
Page 1. You main page where the user will be typing, and where the auto suggest will show up.
(For this example Default.aspx)
Page 2. A data page that will retrieve the data to present as an auto suggest option.
(For this example LookUp.aspx)
The following Javascript functions (In this example in the JSFile.js):
//======================================
//======================================
//============DO NOT REMOVE=============
//======================================
// Created by Rajib Ahmed
// http://www.ProgTalk.com
//======================================
//======================================
//======================================
var req;
var CurrentDIV;
//Set up to use javascript to call pages for data lookup
//YOU DO NOT NEED TO CHANGE ANYTHING BELOW
function Initialize()
{
try
{
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e)
{
try
{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(oc)
{
req = null;
}
}
if( !req && typeof XMLHttpRequest != "undefined" )
{
req = new XMLHttpRequest();
}
}
//sends the query to desired page, and returns to div autocomplete
//based on what the user typed
//key paramater has what the user typed.
//div paramater states, which div to stick the data back to.
function SendQuery(key, MyDiv, url)
{
if ( key == null || key.length == 0 )
{
document.getElementById(MyDiv).innerHTML = "";
HideDiv(MyDiv);
return;
}
CurrentDIV = MyDiv;
Initialize();
var url= url + "&k=" + key + "&MyDiv=" + MyDiv;
if( req != null)
{
req.onreadystatechange = Process;
req.open("GET", url, true);
req.send(null);
}
}
//checks is status was good when calling url for data lookup
function Process()
{
if (req.readyState == 4)
{
// only if "OK"
if (req.status == 200)
{
if(req.responseText=="")
HideDiv(CurrentDIV);
else
{
//alert(req.responseText);
ShowDiv(CurrentDIV);
document.getElementById(CurrentDIV).innerHTML =req.responseText;
}
}
else
{
document.getElementById(CurrentDIV).innerHTML=
"There was a problem retrieving data:<br>"+req.statusText;
}
}
}
//Show Div Section in html
function ShowDiv(divid)
{
if (document.layers) document.layers[divid].display="block";
else document.getElementById(divid).style.display="block";
}
//Hide Div Section in html
function HideDiv(divid)
{
if (document.layers) document.layers[divid].display = "none";
else document.getElementById(divid).style.display="none";
}
//Load selected value into textbox, and hide div
function SetTextbox( TextboxID, data, MyDiv )
{
document.getElementById(TextboxID).value = data;
if ( MyDiv.length > 0 )
{
HideDiv( MyDiv );
}
}
C# Source Code, and How Our Sample Page WorksNow that we have the the javascript code, we will take a look at our Default.aspx page.
Here the main controls we will be concentrating on are the two textboxes.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
If you go over to the html, you will notice that are two DIV's below each textbox.
This is what will load our auto suggestion options.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
How to sync which textbox with which div?I didn't want to hardcode the div names with the textbox, and wanted to have it in a versatile way, where I can show any div
with suggestions from any textbox. This got me to think, and I engineered the javascript functions above which will take
paramaters to know what to fill with which options.
The code for the Default.aspx page is very simple. Nothing else is necessary except what is below.
This will make life so much easier, when you know all you need to do to add another autosuggest textbox is to create the
textbox, and call some existing div, or just a new div with just one line of code (4 lines if you write it out like me ).
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.TextBoxCategory.Attributes["autocomplete"] = "off";
this.TBShipmentName.Attributes["autocomplete"] = "off";
//Add attribute to call js to fetch data
//using the JavaScript function: SendQuery
//Paramaters include
// 1. The current typed text value
// 2. Div ID where to show similar results
// 3. URL to call by AJAX passing Mode to so we know what to query
// 4. Textbox where to return the data
this.TextBoxCategory.Attributes["onkeyup"] = "SendQuery(this.value, '" +
this.DivAutoCompleteCategory1.ClientID +
"', '/HowToCreateAnAutoSuggest/LookUp.aspx?Mode=Category&TB=" +
this.TextBoxCategory.ClientID + "')";
this.TBShipmentName.Attributes["onkeyup"] = "SendQuery(this.value, '" +
this.DivAutoCompleteShipmentInfo.ClientID +
"', '/HowToCreateAnAutoSuggest/LookUp.aspx?Mode=Shipment&TB=" +
this.TBShipmentName.ClientID + "')";
}
}
}
Now we will see the LookUp.aspx pageThe LookUp.aspx page will perform the lookup. Here we do not have any html code, which can be observed in the html source code section. You should not, I repeat, SHOULD NOT add any items to this page. It will ruin what is returned to the Default.aspx page. If you know what you are doing, then go for it.

Here we see what keys where typed into the textbox. Using this information, we will lookup our database, which is the
Northwind database. The two different textboxs actually look up two different tables in the same database. One will look
up the Category table, while the other looks up the Orders table. This page knows what query to run, by looking at the mode
which was passed to us:
public partial class LookUp : System.Web.UI.Page
{
protected void Page_Load(object sender, System.EventArgs e)
{
//keyword checks what was type, mode sets the what query we do,
//TB tells us where to enter the data, and MyDiv tells us which div we are working with
//Modify this to a Stored Procedure for added security.
//If you cannot or do not want to use stored procedures, then
//make sure the query string does not pass a semicolon(;)
//That is a simple way to block most sql hijacking.
string keyword = Request["k"];
string Mode = Request["Mode"];
string ReturnTextbox = Request["TB"];
string MyDiv = Request["MyDiv"];
if (keyword != null && Mode != null && keyword.Trim().Length > 0)
{
//build div items based on what is in database, and what user typed.
string sql = "";
if (Mode == "Category")
{
sql = "SELECT distinct TOP 5 CategoryName from Categories Where CategoryName like '" +
keyword.Replace("'", "''") +
"%'";
}
else if (Mode == "Shipment")
{
sql = "SELECT distinct TOP 5 ShipName from Orders Where ShipName like '" +
keyword.Replace("'", "''") +
"%'";
}
else
{
return;
}
//Here we will fetch the data from the database, and write it back to the default page
DataSet ds = new DataSet();
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection();
conn.ConnectionString = "Data Source=YOURDATASOURCE;Initial Catalog=Northwind;" +
"Persist Security Info=True;" +
"User ID=YOURUSERID;" +
"Password=PASSWORD";
System.Data.SqlClient.SqlDataAdapter adapter =
new System.Data.SqlClient.SqlDataAdapter(sql, conn);
adapter.Fill(ds);
if (ds != null && ds.Tables.Count > 0)
{
DataTable dt = new DataTable();
dt = ds.Tables[0];
foreach (DataRow row in dt.Rows)
{
string mydata = row[0].ToString();
if (ReturnTextbox != null && ReturnTextbox.Trim().Length > 0)
{
//Write to default page, with selection options.
if (MyDiv == null || MyDiv.Trim().Length == 0)
{
Response.Write("<div onmouseover=\"this.style.cursor='pointer';\"" +
"onmouseout=\"this.style.cursor='pointer';\"" +
"onclick=\"SetTextbox('" +
ReturnTextbox.Trim() + "','" +
mydata + "', '');\">" +
"<font size='2' face='Tahoma'><B>" +
mydata +
"</B></font>" +
"</div>");
}
else
{
Response.Write("<div onmouseover=\"this.style.cursor='pointer';\"" +
"onmouseout=\"this.style.cursor='pointer';\"" +
"onclick=\"SetTextbox('" +
ReturnTextbox.Trim() + "','" +
mydata + "', '" +
MyDiv + "');\">" +
"<font size='2' face='Tahoma'><B>" + mydata + "</B></font>" +
"</div>");
}
}
else
{
Response.Write("<div><font size='2' face='Tahoma'><B>" +
mydata + "</B></font></div>");
}
}
}
}
}
}
Here is the sample in action:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Typing C in the Category field:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Typing D in the Ship Name field:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Selecting Category from the Auto Suggest:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Selecting Ship Name from the Auto Suggest:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
I worked very hard to make this article so it can be useful for others. Please leave me some feedback if you have any opinion, good or bad.
Was this article helpful? Don't forget to rate it. Ratings helps community members identify top & useful articles.