01 July 2008

Update on Rails, jQuery, autocomplete

Today I changed my auto_complete_jquery plugin (which I blogged about previously) to work with a different jQuery autocomplete plugin (that's not confusing is it?!). Previously, I'd been using the "jquery-autocomplete" plugin, but had been having problems with it always being case sensitive, and with it being pretty darn slow. To solve that, I wound up switching to Dylan Verheul's jquery autocomplete plugin, which is fantastic! So, I had to update my plugin (literally changed two lines, along with the readme and some comments).

So, what does it all mean? First, things are no longer case-sensitive (although you can tweak that if you need it, see the docs for DV's jquery plugin). Second, the speed is near instant, and if it's taking any time at all, there's now a CSS style you can set to show an indicator while the AJAX call is running (nice!). Further, there are a slew of options you can set, but one of the coolest things is the ability to set a formatter JavaScript function to adjust the display of the returned results, but without affecting the actual value that is placed in your text field. This is really cool for providing further information about a given matched item. For example, I use it to display, on a line below the matched name, the location of the item. There's an interactive example of this on Dylan Verheul's site.

I highly recommend updating all around on this. For those that might be using my prior version, the changes you'd need to make are:


  • Change your JavaScript calls that make a HTML input into an auto-complete from this format:

    $("input#post_title").autocomplete({ ajax: "auto_complete_for_post_title" })

    to this:

    $("input#post_title").autocomplete("auto_complete_for_post_title")


  • Update to the HEAD of my plugin.

  • Remove the old jquery.ui.autocomplete*.js files, and install Dylan's single jquery.autocomplete.js file, updating your JS includes accordingly. Same goes for the stylesheet.



Note, to do the cool 2nd line output of auto-complete items, you will need to write your own auto-complete Rails action, which means you don't need my plugin :) I may update my plugin at some point so you can pass a block in to the autocomplete function to create this same scenario, but this is pretty specific stuff, so we'll see. As a very brief set of instructions to do this, you can essentially copy-paste the auto-complete method that gets defined by my plugin, and then update what you return as text. To do the 2nd line bit, you want to return items in the format, "item|2nd line stuff", (so use the pipe symbol to separate the two lines). Then, you can use a simple JavaScript formatter function like:

function formatAutocompleteItem(row) {
return row[0] + "<br><i>" + row[1] + "</i>";
}


Then, update your call to the jQuery autocomplete that sets up a field as autocomplete to be:

$("input#post_title").autocomplete("auto_complete_for_post_title", { formatItem:formatAutocompleteItem })


Enjoy!

6 comments:

Unknown said...

Great stuff.

How do you get it to work with a hidden ID when you don't want to submit the text field?

Normally you'd want this when you use autocomplete as a nice selector when you have what would otherwise be a vast dropdown.

cheers

Anonymous said...

Couldn't seem to get this working... every time I type into the text field I get the following:

Parameters: {"action"=>"show", "id"=>"auto_complete_for", "q"=>"13", "controller"=>"admin/posts"}
Post Columns (0.001107) SHOW FIELDS FROM `posts`
Post Load (0.000172) SELECT * FROM `posts` WHERE (`posts`.`id` = 0)


ActiveRecord::RecordNotFound (Couldn't find Post with ID=auto_complete_for):

Anonymous said...

et, I get the same errors. It's as though the plugin isn't registering so the route is taken as though it were a regular REST request to the show action. I'll post back if I'm able to figure it out.

Robert Dempsey said...

Any update to the error mentioned by the above users? I'm getting the exact same error and can't get past it. tThanks.

jancsi said...

Merci bien!!

Thought I'd mention in case someone else had the 'id' => 'auto_complete_for...' problem

Just add a route

map.connect ':controller/:id/auto_complete_for_model_field', :action => 'auto_complete_for_model_field', :format => 'json'

Also I didn't use model.text_field, just text_field.

jancsi said...

I wanted to paste some example code but the blog wouldn't let me.

If you do a custom auto_complete_for_model_field method, put your field entries in an array, join the array with "\n" (eg "Jim\nJohn\nKarl") and render colon-'inline' equals-greater-than quote less-than-percent-equals @fields percent greater-than quote.

Just throw auto_complete a string with entries separated by "\n" and it'll do the rest.