mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
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
This commit is contained in:
parent
f0608c9165
commit
521d5fdc72
2 changed files with 57 additions and 16 deletions
|
@ -49,6 +49,7 @@ require 'action_controller/caching'
|
|||
require 'action_controller/components'
|
||||
require 'action_controller/verification'
|
||||
require 'action_controller/streaming'
|
||||
require 'action_controller/auto_complete'
|
||||
|
||||
require 'action_view'
|
||||
ActionController::Base.template_class = ActionView::Base
|
||||
|
@ -69,4 +70,5 @@ ActionController::Base.class_eval do
|
|||
include ActionController::Components
|
||||
include ActionController::Verification
|
||||
include ActionController::Streaming
|
||||
include ActionController::AutoComplete
|
||||
end
|
||||
|
|
|
@ -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
|
|||
# <tt>:update</tt>:: 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'
|
||||
# <tt>:with</tt>:: A Javascript expression specifying the
|
||||
# parameters for the XMLHttpRequest. This defaults
|
||||
# to 'value', which in the evaluated context
|
||||
# refers to the new field value.
|
||||
# <tt>:indicator</tt>:: 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)
|
||||
"<ul>#{entries.map { |entry| '<li>' + (phrase ? highlight(entry[field],phrase) : h(entry[field])) + '</li>' }.join}</ul>" 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
|
||||
|
|
Loading…
Reference in a new issue