Using a JSON string prepared in ColdFusion for Autocomplete use in jQuery

The below post was originally written in September 2012 for my Tumblr. I still use this set of tools for auto-complete when creating questionnaires for my current employer and later used it for internal  uses to auto-fill entries in some of their tools and one of our clients for an entry form their vendors use.

The goal was to use jQuery UI’s Autocomplete widget and the source for what would fill in such entries was a query result set, namely a list of questions.

The next day, I decided that I wanted Autocomplete restricted to strings that started with what was being entered but to still be case insensitive.

The process went as follows:

-Use AJAX to call a CFC that would query the questions

-Return the list in an acceptable JSON structure for use in Javascript/jQuery.

-Place that array as the source for Autocomplete

-Set up Autocomplete to my specific requirements

Here is our basic ajax call. We make the result a variable since that given result is what we will be passing to Autocomplete.

var arrQst = $ajax({
	url: "path/Filename.cfc?method=GetQuestions"
	,async: false
	,type: 'POST'
}).responseText;

Here is our CFC function:

<cffunction
	name="GetQuestions"
	access="remote"
	returntype="string"
	returnformat="plain"
	output="false"
	hint="I return a list of questions">
	
	<cfquery name="qryQuestions" datasource="master">
		Select Question
		From tblQuestion
	</cfquery>
	
	<cfloop query="qryQuestions">
		<cfset returnStruct = StructNew() />
		<cfset returnStruct["value"] = qryQuestions.qst />
		<cfset ArrayAppend(result,returnStruct)/>
	</cfloop>
	
	<cfreturn serializeJSON(result) />

</cffunction>

The part after the query is the part of interest to us. That is what puts the results into a JSON structure that our jQuery will understand.

Here is our HTML input

<input type="text" name="inputstring" id="inputstring">

Here is our jQuery for Autocomplete:

function split( val ) {
	return val.split( /,\s*/ );
}
function extractLast( term ) {
	return split( term ).pop();
}

$("#inputstring#")
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
	if ( event.keyCode === $.ui.keyCode.TAB &&
			$( this ).data( "autocomplete" ).menu.active ) {
		event.preventDefault();
	}
}).autocomplete({
	minLength: 1,
	source: function(request,response) {
		var StringList = jQuery.parseJSON(arrQst);
                var matches = $.map( StringList, function(q) {
		//Check this pattern, starts with what is entered, 
                       //case insensitive
		var patt = new RegExp("^" + request.term, "i");
		//variable to hold if pattern matches
		var isMatch = patt.test(q.value);
		
		//if so return the string
		if(isMatch == true) {
			return q;
		}
	});
		response (matches);
	},
	focus: function() {
		// prevent value inserted on focus
		return false;
	},
	select: function(event, ui) {
		var terms = split( this.value );
		// remove the current input
		terms.pop();
		// add the selected item
		terms.push( ui.item.value );
		this.value = terms;
		return false;				   
	}
});

There were some extra steps that I must have researched nearly a year ago with the split and extractLast, from an older project, so I won’t be going over them. Here, the part of interest to us is what’s under source. There, we go over our array, check it against a regular expression to determine if the beginning what is being entered matches the values being checked in the array. We disregard case though. That way, if our user enters “the long…,” it will bring up any string that starts with those letters.

And voila, fantastic Autocomplete functionality, should be quite useful for increased productivity.