From 521d5fdc72f776e255454a4229bfd1a110da8bc3 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 26 Jun 2005 14:23:36 +0000 Subject: Added auto_complete_for to controller and text_field_with_auto_complete to view to make it really, really easy to do Google Suggest style interfaces git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1525 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../lib/action_view/helpers/javascript_helper.rb | 71 +++++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'actionpack/lib/action_view') diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 31c15d222c..7b857f4f18 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -17,7 +17,7 @@ module ActionView module JavascriptHelper unless const_defined? :CALLBACKS CALLBACKS = [ :uninitialized, :loading, :loaded, :interactive, :complete ] - AJAX_OPTIONS = [ :url, :asynchronous, :method, :insertion, :form, :with ].concat(CALLBACKS) + AJAX_OPTIONS = [ :url, :asynchronous, :method, :insertion, :form, :with, :update ].concat(CALLBACKS) JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts') end @@ -220,39 +220,50 @@ module ActionView # :update:: Specifies the DOM ID of the element whose # innerHTML should be updated with the autocomplete # entries returned by the Ajax request. - # Defaults to field_id + '_autocomplete' + # Defaults to field_id + '_auto_complete' # :with:: A Javascript expression specifying the # parameters for the XMLHttpRequest. This defaults # to 'value', which in the evaluated context # refers to the new field value. # :indicator:: Specifies the DOM ID of an elment which will be # displayed while autocomplete is running. - # - def remote_autocomplete(field_id, options = {}) + def auto_complete_field(field_id, options = {}) function = "new Ajax.Autocompleter(" function << "'#{field_id}', " - function << "'" + (options[:update] || "#{field_id}_autocomplete") + "', " + function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', " function << "'#{url_for(options[:url])}'" js_options = {} - js_options[:callback] = "function(element, value) {return #{options[:with]}}" if options[:with] + js_options[:callback] = "function(element, value) { return #{options[:with]} }" if options[:with] js_options[:indicator] = "'#{options[:indicator]}'" if options[:indicator] function << (', ' + options_for_javascript(js_options) + ')') - + javascript_tag(function) end # Use this method in your view to generate a return for the Ajax automplete requests. # - # Example Action: - # @items = Item.find(:all, :conditions => [ 'LOWER(description) LIKE ?', - # '%' + params[:for].downcase + '%' ], 'description ASC') - # render :layout => false - # - # Example View: - # <%= autocomplete_responder @items, 'description' %> - def autocomplete_responder(entries, field, phrase = nil) - "" if entries + # Example action: + # + # def auto_complete_for_item_title + # @items = Item.find(:all, :conditions => [ 'LOWER(description) LIKE ?', + # '%' + params[:for].downcase + '%' ], 'description ASC') + # render :inline => '<%= auto_complete_result(@items, 'description') %>' + # end + # + # The auto_complete_result can of course also be called from a view belonging to the + # auto_complete action if you need to decorate it further. + def auto_complete_result(entries, field, phrase = nil) + return unless entries + items = entries.map { |entry| content_tag("li", phrase ? highlight(entry[field], phrase) : h(entry[field])) } + content_tag("ul", items) + end + + def text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {}) + (completion_options[:skip_style] ? "" : auto_complete_stylesheet) + + text_field(object, method, tag_options) + + content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") + + auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" } }.update(completion_options)) end # Returns a JavaScript snippet to be used on the Ajax callbacks for starting @@ -347,6 +358,34 @@ module ActionView callbacks end end + + def auto_complete_stylesheet + content_tag("style", <<-EOT + div.auto_complete { + width: 350px; + } + div.auto_complete ul { + border:1px solid #888; + margin:0; + padding:0; + width:100%; + list-style-type:none; + } + div.auto_complete ul li { + margin:0; + padding:3px; + } + div.auto_complete ul li.selected { + background-color: #ffb; + } + div.auto_complete ul strong.highlight { + color: #800; + margin:0; + padding:0; + } + EOT + ) + end end end end -- cgit v1.2.3