After a quick Google search, I found a pretty good plugin that looked like it would do what I wanted. However, there was a pretty big difference in how the two plugins work. Ajax.Autocompleter must return an unordered list (
<ul>
), with each suggestion rendered inside its own list item (<li>
). Piece of cake.However, the jQuery Autocompleter expects a string, with each suggestion rendered on its own line. This threw me for a loop at first, since ColdFusion isn't always the best at dealing with whitespace. After a little thought, here's what I came up with.
index.cfm
<link rel="stylesheet" type="text/css" href="jquery.autocomplete.css" />
<script src="jquery-1.3.2.js"></script>
<script src="jquery.autocomplete.js"></script>
<script type="text/javascript">
$().ready(function() {
$('#search').autocomplete('UserService.cfc?method=autocomplete&_cf_nodebug=true', {
multiple: true,
formatItem: function(row) {
var user = JSON.parse(row.toString());
return user.name;
},
formatResult: function(row) {
var user = JSON.parse(row.toString());
return user.email;
}
});
$('#search').result(function(event, data, formatted) {
var user = JSON.parse(data.toString());
alert('You selected user '+user.id);
});
});
</script>
<input type="text" id="search" name="search" size="60" />
UserService.cfc
component {
remote void function autocomplete(required string q) {
// get the users
var users = searchUsers(arguments.q);
var result = [];
var i = "";
for (i=1; i <= arrayLen(users); i++) {
// build the user record
var user = {};
// maintain lowercase keys
user["id"] = users[i].id;
user["name"] = users[i].name & " (" & users[i].email & ")";
user["email"] = users[i].email;
// serialize the user record and append it to the result
arrayAppend(result, serializeJSON(user));
}
// convert the result from an array to a list, with each user on its own line
var html = arrayToList(result, chr(10));
// output the JSON result
writeOutput(html);
}
public array function searchUsers(required string search) {
// normally this would query the db,
// but for this demo I'll just create a static array of users
var users = [
{id="1", name="Adam", email="adam@email.com"},
{id="2", name="Bob", email="bob@email.com"},
{id="3", name="Brady", email="brady@email.com"},
{id="4", name="John", email="john@email.com"},
{id="5", name="Kaitlyn", email="kaitlyn@email.com"},
{id="6", name="Leanne", email="leanne@email.com"},
{id="7", name="Lisa", email="lisa@email.com"},
{id="8", name="Mike", email="mike@email.com"},
{id="9", name="Nate", email="nate@email.com"},
{id="10", name="Ryan", email="ryan@email.com"},
{id="11", name="Sean", email="sean@email.com"},
{id="12", name="Tony", email="tony@email.com"},
{id="13", name="Tyler", email="tyler@email.com"}
];
return users;
}
}
On a side note, JSON.parse() is a built-in function only available to newer browsers, like Firefox 3.5 and IE 8.0. Does anybody know of a good plugin to accommodate older browsers? Something similar to Prototype's String.evalJSON would be preferred.
You could use ColdFusion.JSON.decode to parse the JSON string - check the docs:
ReplyDeletehttp://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=JavaScriptFcns_07a.html
cool other people actually know of _cf_nodebug=true, I wish more people used it
ReplyDelete@Todd: I never thought of that. I'd prefer to keep my JavaScript code server-language agnostic, but I don't imagine I'll be moving away from ColdFusion anytime soon, so that should work just fine.
ReplyDelete@Josh: I only know of it because of you, so don't get too excited. Also, it feels a little hacky to me for some reason, but I don't know why.
The place to find all things JSON is http://json.org There's a create/proces JSON for almost every language, including JavaScript. You should also check out jQuery, which is excellent at providing a consistent API despite browser differences.
ReplyDeleteDurr, sorry, I didn't have enough coffee obviously, because you have "jQuery" all over your post. To be more helpful, based on listening to jQuery podcasts with the creators and heavy users, json2 is a highly preferred solution: JSON in JavaScript
ReplyDelete@Tony, Yeah I found json2 as well and it seems to be what I want. However, when I was testing it with my current code set I was running into issues with converting strings to JSON. Apparently Prototype can evaluate JSON strings with keys that are wrapped in single quotes ({'name': 'Tony'}) or double quotes ({"name": "Tony"}), but json2 only supports double quotes. I'm not saying Prototype is right, but just that I had problems.
ReplyDeleteA simple solution was to update JSON.parse to use eval("("+text+")") rather than eval('('+text')'), which was a lot easier than updating all of my code to make sure all of my JSON strings used double quotes.