My Blog List

Friday, August 13, 2010

Autosuggest Example Using ColdFusion

So I got a chance to try this one out. I’ve written auto-suggest boxes in GXT and plain old JS and while its a little harder to get the same level of control and customization ,CF8’s autosuggest is pretty neat for most simple use-cases and for those wanting to whip up an app quickly. I know CF9 has much better handles to the autosuggest object (looking forward to that here's a preview), but till then ..here goes!

Here’s an example of a user looking up an employee by last name.

In this example I use 2 files: one (loopkup.cfm) to display the autosuggest box and the other (a CFC ,MCRequestServer.cfc) to fetch data for it.

First the auto-suggest box code:

  1: <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
  2: <html>
  3: 	<head>
  4: 		<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
  5: 		<title>Search Trainees</title>
  6: 		<link href="AppStyles.css" rel="stylesheet" type="text/css" />
  7: 		<script>
  8: 			/**
  9: 			 * This method handles all bind errors. I'm just alerting.
 10: 			 * args:
 11: 			 * 	i. HTTPStatusCode- Error Code.number
 12: 			 *	ii.message- any message you want to display
 13: 			 */
 14: 			function handleBindError(HTTPStatusCode,message)
 15: 			{
 16: 				alert("Error Code: "+HTTPStatusCode+":\n"+message);
 17: 			}
 18: 			/**
 19: 			 * This method attaches an itemSelect event handler to handle
 20: 			 *  selections (using both mouse and keys).Called by ajaxOnLoad below.
 21: 			 */
 22: 			var init = function()
 23: 			{
 24: 				/** get the autosuggest object */
 25: 				autosuggestobj = ColdFusion.objectCache['TraineeSearchBox'];
 26: 				/** attache an itemselect event handler*/
 27: 				autosuggestobj.itemSelectEvent.subscribe(handleSelection);
 28: 			}
 29: 			/**
 30: 			 * This method handles all selections from the autosuggest list
 31: 			 * arg-
 32: 			 *	i. event-the event name. in this case "itemSelect"
 33: 			 *	ii.args- an array with the follwing data
 34: 			 *			 args[0]- Name/ID of the autocomplete component
 35: 			 *			 args[1]- The actual <LI> element that the user selected
 36: 			 *			 args[2]- The value selected.			 			 
 37: 			 */
 38: 			var handleSelection = function(event,args)
 39: 			{
 40: 				/** Display selection, you could do ur custom code here */
 41: 				document.getElementById("SearchTraineeSpan").innerHTML=args[2];
 42: 			}
 43: 		</script>
 44: 	</head>
 45: 	<body bgcolor="beige">		
 46: 		<cfform>
 47: 			<cfinput type="text" 
 48: 				name="TraineeSearchBox" 
 49: 				autosuggest="cfc:MCRequestServer.getEmployeesByLastName({cfautosuggestvalue})"
 50: 				onbinderror="handleBindError"
 51: 				showautosuggestloadingicon="true"
 52: 				autoSuggestMinLength="1"
 53: 				tooltip="Type employee last name"					
 54: 				onclick="this.value=''"	
 55: 				 />
 56: 				 <!--- Causes the specified JavaScript function to run when the page loads. --->
 57: 				 <cfset ajaxOnLoad("init")>
 58: 		<br>
 59: 		<span id="SearchTraineeSpan"></span>
 60: 		</cfform>
 61: 		
 62: 	</body>
 63: </html>
 64: 

Couple of points to note:


1.  The below line binds the textbox to a CFC called MCRequestServer and more specifically, a function called getEmployeesByLastName(). The argument cfautosuggestvalue is a CF keyword which represents the text the user entered in the textbox.

  1: autosuggest="cfc:MCRequestServer.getEmployeesByLastName({cfautosuggestvalue})"



2. The below line causes the specified JavaScript function init() to run when the page loads. This is to avoid timing issues.

  1: <cfset ajaxOnLoad("init")>

And here is the second file MCRequestServer.cfc. It just returns an array fo employee names.

  1: <cfcomponent displayname="MCRequestServer" hint="Handles all bind requests" output="false">
  2: 
  3: <cffunction name="getEmployeesByLastName" displayname="getEmployeesByLastName" access="remote" output="false" returntype="array">
  4: 		<cfargument name="suggestvalue" required="true" />
  5: 		<!--- The function must return suggestions as an array. --->
  6: 		<cfset var EmplNamesArray = ArrayNew(1) />
  7: 		<cftry>
  8: 			<!--- Get all unique last names that match the typed characters. --->
  9: 			<cfstoredproc datasource="DB" procedure="getMatchingEmployees" >			
 10: 			<cfprocparam type="in" dbvarname="@LastName" cfsqltype="CF_SQL_VARCHAR" value="#arguments.suggestvalue#"  >
 11: 				<!--- Out variable --->
 12: 				<cfprocresult name="rsEmplnames">
 13: 			</cfstoredproc>
 14: 			<!--- Convert the query to an array. --->
 15: 			<cfloop query="rsEmplnames">
 16: 				<cfset arrayAppend(EmplNamesArray, Lastname & ", " & FirstName ) />
 17: 			</cfloop>
 18: 			<cfreturn EmplNamesArray />
 19: 			<cfcatch type="any">
 20: 				<cfset arrayAppend(EmplNamesArray, "Error occurred") />
 21: 				<cfreturn EmplNamesArray />
 22: 			</cfcatch>
 23: 		</cftry>
 24: 	</cffunction>
 25: 
 26: 
 27: </cfcomponent>
 28: