Welcome to EMC Consulting Blogs Sign in | Join | Help

Rory Street's EMC Consulting Blog (2004 - 2011)

This blog has now moved to http://rory.streetfamily.info - please update your subscriptions if you wish to receive new content.

Google Suggest - Can .NET play too?

Looking through the various blog posts and Google Suggest still seems to be a topic everyone is interested in. With a further bit of investigation I discovered what Google is doing is nothing new, all they are doing is using a Javascript method that has been around for a while now, but of course in a rather clever way. Most developers seem to think of web browsers as old style posting back to the server type of client with very little else you can do to talk to the server from the client unless you have a Java or ActiveX app installed (urrrghh security problems!).

So introduce the very humble JavaScript code that is available on so many browsers today and a with a bit of help from some samples on Jim Ley's site (This site is well worth a look and rich in information on JavaScript RPC) , I managed to put together a quick example of a "Google Suggest" type interface using APS.NET.

I call it Cartoon Character Search (Okay it was late at night and there was still a bit of Xmas spirit in the air!)

Cartoon Search

The interface works on basically the same principle as Google Suggest (however not at all as advanced). The user starts to type in the names of a cartoon character and as they do a request is made back to the server using the JavaScript XML HTTPRequest object to look up the names in an underlying database. In this case I made do with a .NET DataTable object instead. Now don't let the fact that it says XML HTTPRequest put you off, this is only a method and I have not used any XML in this example.

Below is the code I used for the page shown above. The page is created completely in HTML so you should be able to just cut and paste it in.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Cartoon Character Search - Example created By Rory Street</title>
<script language=javascript>
 var xmlhttp=false;
 var _ai = 0;
  
  // -----> This method was provided from Jim Ley's website 
  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  // JScript gives us Conditional compilation, we can cope with old IE versions.
  // and security blocked creation of the objects.
  try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
  try {
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
  xmlhttp = false;
  }
  }
  /*@end @*/
  
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
  xmlhttp = new XMLHttpRequest();
  }
  // -->>>>>> End method
  
  
  // Over here we make a call back to our server side page and return the results from our query 
  // to a DIV tag sitting under the text box
  function methDataGet(strMethod,strValue,returnDiv)
  {
  xmlhttp.open("GET", "WebForm1.aspx?str=" + strValue,true);
  
   xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
   document.getElementById(returnDiv).innerHTML = xmlhttp.responseText 
   document.getElementById(returnDiv).style.visibility = 'visible'
   }
   }
   xmlhttp.send(null)
  }
  
  function selectName(oName)
  {
   if(oName)
   {
    document.frmTest.txtInput.value = oName.innerHTML;
    
   }
   //lostfocus('theDiv');
  }
  
  function lookmeup(oElement,oDiv,evt)
  {
   //Detect if the user is using the down button
   if(detectKeyPress(evt)==38)
   {
    keyUpList()
   }
   else if(detectKeyPress(evt)==40)
   {
    keyDownList()
   }
   else if(detectKeyPress(evt)==13)
   {
    selectName(document.getElementById('ai'+_ai));
   }
   else
   {
   lostfocus(oDiv);
   methDataGet("methGetAddressName",oElement.value,oDiv)
   }
  }
  
  function keyDownList()
  {
   if(_ai!=0)
   {
    uhAddress(document.getElementById('ai'+_ai))
   }
   
   _ai = _ai +1;
   if(document.getElementById('ai'+_ai))
   {
    hAddress(document.getElementById('ai'+_ai))
    selectName(document.getElementById('ai'+_ai))
   }
   else
   {
    _ai = _ai -1;
    hAddress(document.getElementById('ai'+_ai))
    selectName(document.getElementById('ai'+_ai))
   }
  }
  
  function keyUpList()
  {
   if(_ai!=0)
   {
    uhAddress(document.getElementById('ai'+_ai))
   }
   
   _ai = _ai -1;
   if(document.getElementById('ai'+_ai))
   {
    hAddress(document.getElementById('ai'+_ai))
    selectName(document.getElementById('ai'+_ai))
   }
   else
   {
    _ai = _ai +1;
    hAddress(document.getElementById('ai'+_ai))
    selectName(document.getElementById('ai'+_ai))
   }
  }
  
  //Highlights a div
  function hAddress(tobject)
  {
   if(tobject)
   {
    tobject.style.background = 'blue'
    tobject.style.color= "white"
   }
  }
  
  //unhighlights a div
  function uhAddress(tobject)
  {
   if(tobject)
   {
    tobject.style.color= "black"
    tobject.style.background = '#ffffff'
   }
  }
  
  //Detects what key was pressed
  function detectKeyPress(evt)
  {
   evt = (evt) ? evt : (window.event) ? event : null;
   if (evt)
   {
    var charCode = (evt.charCode) ? evt.charCode :
       ((evt.keyCode) ? evt.keyCode :
       ((evt.which) ? evt.which : 0));
    return charCode; 
   }
  }
  
  
  function lostfocus(oDiv)
  {
   if(document.getElementById(oDiv).style.visibility = 'visible')
   {
    document.getElementById(oDiv).style.visibility = 'hidden';
    _ai=0;
   } 
  }
</script>
</head>
<body onclick="javascript:lostfocus('theDiv')">
<h1>Cartoon Character Search</h1>
<form name="frmTest" method=post action="">
  <input type=text size=40 name="txtInput" id="txtInput"  onkeyup="javascript:lookmeup(this,'theDiv',event)"/><br>
  <div name="theDiv"  id="theDiv" style="position: relative; width: 200px; height: 70px; z-index: 1;border: 1px solid #00FFFF; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px;background-color: #FFFFFF;visibility:hidden;overflow: auto"></div>
  
</form>
</body>
</html>

I then created a C# ASP.NET project called TestRemoteAPI and created a page called WebForm1.ASPX. On this page I went into the HTML and removed all of it and then inserted a Literal control onto the page. I then added the following code to the code behind on the page.

Place the following just inside the page class: You will also need System.Data()

private DataRow[] drarray;

In the Page_Load event put the following code. This picks up a request from our client side HTML as a simple request object.

private void Page_Load(object sender, System.EventArgs e)
 {
 
 // Put user code to initialize the page here
 DataTable dTable = GetCharacters();
 
 drarray = dTable.Select("Name like '" + Request.QueryString["str"] + "*'");
 int i=0;
 
 for(int r=0 ; r < drarray.Length; r++)
 {
 i=i+1;
 Literal1.Text=Literal1.Text + "<div id=\"ai" + i.ToString() + "\" name=\"ai" + i.ToString() + "\">" +drarray[r]["Name"] + "</div>";
 }
 
 }

The following code can go beneath the Page_Load event method, all this does is emulates a database for us.

private DataTable GetCharacters()
 {
 DataTable dtTempTable = new DataTable("MyCharacters");
 dtTempTable.Columns.Add("Name");
 DataRow dr;
 
 dr = dtTempTable.NewRow();
 
 dr["Name"]="Daffy";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 
 dr["Name"]="Donald";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Goofy";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Porky";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Road Runner";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Tweety";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Taz";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Micky";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Bat Fink";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Bat Man";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Marvin the Martian";
 dtTempTable.Rows.Add(dr);
 
 dr = dtTempTable.NewRow();
 dr["Name"]="Bux Bunny";
 dtTempTable.Rows.Add(dr);
 
 return dtTempTable;
 }

So how does it all work?
Well the HTML page we are using is making an XML HTTPRequest back to our server side page WebForm1.aspx (note the HTML page can be called anything but must sit in the same directory as WebForm1.aspx unless you want to change the path names in the JavaScript). When the server side page gets the request it draws the results into an ASP.NET Literal control on the page, each result contained within a DIV. The JavaScript client side takes the HTML of the page sent to it and places this inside a DIV client side (this is the drop down box you see appear below the text box). When the user presses the down and up arrow keys on their keyboard it selects the various options, I didn't put a mouse selection method in but this should be very easy to do with an onlick event. At the moment the page only shows you different selections based on what you are typing in but can quite easily be made to do all sorts of things. The nice thing about this method is it works on most browsers and I have tested it on Mozilla and IE without any problems. Playing around with it you will probably realise there are hundred of applications this type of method can be used on and it is so very simple to use.

If you have any suggestions or comments or have found a way to improve on the code please let me know I would love to hear from you. It is by no means perfect and was just a little something I put together from various examples around the net.

Published 30 December 2004 16:01 by rory.street

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

rory.street said:

Oops I hadn't noticed that my colleague Christian Wade had also posted an article on client side call backs in ASP.NET v2(Whidbey) which does a very nice job of the whole thing with very little code. The version I have posted here can be used on any platform the user just needs to point the client HTML page back to a Java or PHP page that does the same as the ASPX page I created for this example.
December 30, 2004 16:25
 

Ogp-consult said:

If you you would like to use the Google Suggest data in your .net Apps I have made a simple interface that gets the data and creates an array of instances of a "GoogleSuggestion" class. Download the source code here: http://www.ogp-consult.dk/index.php?page=google-suggest-api-for-net
March 25, 2007 22:11

Leave a Comment

(required) 
(optional)
(required) 
Submit
Powered by Community Server (Personal Edition), by Telligent Systems