Marko Anastasov wrote this on July 25, 2009

Hacking Rails auto_complete plugin for Prototype

The official Rails plugin for adding auto-complete functionality to your forms which works with Prototype and script.aculo.us is a fair choice which suits most cases. Plus you can always easily write your own auto_complete_for_#{object}_#{attribute} action in the controller to replace the default query. Note that you should probably always consider doing it - by default, the generated query will do a SELECT * ALL from the given table, while a DISTINCT call might suffice:

  def auto_complete_for_post_title
    input = params[post][:title].split(",").last.strip
    posts = Post.all(
      :select => "DISTINCT(title)",
      :conditions => ["LOWER(title) LIKE ?", "%#{input}%"],
      :limit => 10
    )
    resp = "<ul>"
    posts.each { |p| resp << "<li>#{p.title}</li>" }
    resp << "</ul>"
    render :text => resp
  end

Here we will show how to auto-complete for comma separated input. The plugin as it is will generate Javascript code which will always replace any previous value in the input field, while it is often preferred to add things up in some way (eg when entering tags).

Our fork of auto_complete adds an option to pass a custom Javascript function to be called after user selects one of the items from the suggestion list (updateElement for Ajax.Autocompleter, it might have not been available at the time the plugin was written).

<%= text_field_with_auto_complete :post, :title, {}, { :update_element => "function(el) { autoCompleteUpdate(el, 'post_title'); }" } %>

Here’s how autoCompleteUpdate can look like. We want it to keep all previous entries and replace the partial input which triggered the auto-completion with the selected item:

function autoCompleteUpdate(selectedLi, fieldId) {
  var values = $(fieldId).value.split(',');
  var oldVal = '';

  for (i = 0; i < values.length - 1; ++i) {
    oldVal += ', ' + stripWhitespace(values[i]);
  }

  $(fieldId).value = oldVal + ', ' + $(selectedLi).innerHTML;
  $(fieldId).value = $(fieldId).value.substring(2);
}
comments powered by Disqus

About Marko Anastasov

Rendered Text co-founder. Started with code, currently more focused on people and words. Foosball striker and entry-level cyclist.

Suggested Reads

Rails Testing Handbook

A new ebook on building test-driven Rails apps with RSpec and Cucumber.

At Rendered Text, we have a long history with Ruby on Rails. Checking the blog archive reminds me that we published first posts about working with Rails way back in 2009.

———

Rendered Text is a software company. For questions regarding Semaphore, please visit semaphoreci.com. Otherwise, feel free to get in touch any time by sending us an email.