I've blogged recently (see related entries below) on jQuery UI's Autocomplete control. It's a cool control and has something inherit that I really wish ColdFusion's built in control had - the ability to return complex data back to the form. As an example, this lets us return a label and an ID value. You can store the ID in a hidden field and display a name to the user. Even better, you can also a label value. This means you can have both a unique display in the drop down of suggestions that is different from what actually gets shown in the text field. This label can include HTML, which means you can do all kinds of cool stuff. You could - for example, have an autocomplete that uses colors to convey information (perhaps highlighting results that other customers have selected). I whipped up a quick example that shows a cool example of this.

For my new demo I created a search form for my blog comments. The idea would be that you can begin typing a name and see suggestions from the folks who have commented on my blog. The front end code for this is a very slightly modified version of the final example in this blog post.

<script src="jqueryui/js/jquery-1.4.2.min.js"></script> <script src="jqueryui/js/jquery-ui-1.8.custom.min.js"></script> <link rel="stylesheet" href="jqueryui/css/vader/jquery-ui-1.8.custom.css" type="text/css" />

<script type="text/javascript"> $(function() { $("#name").autocomplete({ source: "blogservice.cfc?method=searchpeople&returnformat=json", select:function(event,ui) { $("#email").val(ui.item.email) } }); }); </script>

<form action="test4.cfm" method="post"> name: <input name="name" id="name" /> <input name="email" id="email" type="hidden"> <input type="submit" value="Submit"> </form>

<cfif not structIsEmpty(form)> <cfdump var="#form#" label="Form"> </cfif>

The only thing different here from the earlier blog entry is that I'm pointing to a new service now and I'm using email as the field I'll be storing behind the scenes. Again - if any of this is weird to you, please reread the earlier entry. Now let's look at the service.

component {

remote function searchPeople(string term) { var q = new com.adobe.coldfusion.query(); q.setDatasource("myblog"); q.setSQL("select distinct name, email from tblblogcomments where name like :search limit 0,15"); q.addParam(name="search",value="%#arguments.term#%",cfsqltype="cf_sql_varchar"); var query = q.execute().getResult(); var result = []; for(var i=1; i<=query.recordCount; i++) { result[arrayLen(result)+1] = {}; result[arrayLen(result)]["email"] = query.email[i]; var gimage = "http://www.gravatar.com/avatar/#lcase(hash(query.email[i]))#?s=20&r=pg"; result[arrayLen(result)]["label"] = "<img src='#gimage#' align='left'>" & query.name[i]; result[arrayLen(result)]["value"] = query.name[i]; } return result; }

}

Again - this is pretty similar to the previous entry, but notice that I've added a new label field to my result. Because the label allows for generic HTML, I've prefixed the name value with the Gravatar for their email. I wasn't sure how well this would work, but wow, it worked like a charm.

Edit: I modified the service code to always return my email address. I didn't mean to expose my commenter's email addresses like that. I apologize, and thank you to Todd Rafferty for pointing it out!