Tuesday 25 May 2010

JQuery Autocomplete - How to Create Your Own Callbacks for Selecting Options

This here is a post for the hackers out there.
It involves dealing with the JQuery plugin: Autocomplete (http://docs.jquery.com/Plugins/Autocomplete).

I have been struggling these days over a problem that I think many might have.
The standard Autocomplete as of now can only suggest options and when you select one of those options it
gets written in your input that triggered the autocomplete. It works for most of the cases but at times you
may want that when you select that option multiple inputs to be affected like in this example:


Say that we have these inputs: [address], [city], [state], [zip]

Typing something in the [address] input would give you a list of
addresses and you select for example on of those:
"123 mayham ave, New Los Angeles, 90000". Now you might want
that parts of this address string go into different inputs like
"123 mayham ave" to [address], "New Los Angeles" to [city], "90000" to [zip] etc.
Currently with JQuery Autocomplete this is not really possible.

Here's how I solved this problem:

Step 1

I had to alter a single line of code in the autocomplete.js file (the main plugin file for autocomplete). That line was just plainly replacing the input's value with whatever the selector's value was.
In the function selectCurrent() i changed the line
$input.val(v);
to
options.selectOptionHandler && options.selectOptionHandler(selected) || $input.val(v);
this ensures that if you have a callback function named selectOptionHandler in the options parameter it will use that function istead of changing the input's value. This way you can change whatever you want in your callback using the supplied argument (selected) which is the selectedOption object.

Step 2

Next i declared my custom callback in the options like this:

$('#clinfo-'+addressFields[fx]).autocomplete("./?v=ajax&a=autocomplete_async", {
 cacheLength: 1,
 matchContains: true,
 selectFirst:false,
 dataType: "json",
 
 //this function parses the data supplied by the server side (in case it's a json string)
 parse: function(data) {
  var array = new Array();
  if(data.matches){
   for(var i=0;i<data.matches.length;i++){
    array[array.length] = { data: data.matches[i], value: data.matches[i]["cl_"+data.field], result: data.matches[i]["cl_"+data.field] };
   }
  }
  return array;
 },
 formatItem: autocompleteFormatAddress,
 
 // this is the callback function im talking about 
 selectOptionHandler: function(selectItem){
  $("#clinfo-street").val(selectItem.data.cl_street);
  $("#clinfo-city").val(selectItem.data.cl_city);
  $("#clinfo-zip").val(selectItem.data.cl_zip);
  $("#clinfo-state").val(selectItem.data.cl_state);
 },
 
 extraParams:{
  "field":addressFields[fx],
  client: function(){ return $("#clinfo-client").val()}
 }
 });

Of course, I am supplying the values from the server as a json array with rows
containing the values for street, city, state etc.

If you find this thing helpful let me know or perhaps also tell me if you don't find it so I can explain better.

Write me here if you need the modified version of the autocomplete.js file.


Best of luck!