Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 7450

Show
Ignore:
Timestamp:
09/11/07 02:57:19 (1 year ago)
Author:
david
Message:

Moved ActionController::Macros::AutoComplete into the auto_complete plugin on the official Rails svn #9512 [lifofifo]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r7447 r7450  
    22 
    33* Fixed that resource namespaces wouldn't stick to all nested resources #9399 [pixeltrix] 
     4 
     5* Moved ActionController::Macros::AutoComplete into the auto_complete plugin on the official Rails svn #9512 [lifofifo] 
    46 
    57* Moved ActionController::Macros::InPlaceEditing into the in_place_editor plugin on the official Rails svn #9513 [lifofifo] 
  • trunk/actionpack/lib/action_controller.rb

    r7442 r7450  
    5555require 'action_controller/components' 
    5656require 'action_controller/record_identifier' 
    57 require 'action_controller/macros/auto_complete' 
    5857 
    5958require 'action_view' 
     
    7675  include ActionController::Components 
    7776  include ActionController::RecordIdentifier 
    78   include ActionController::Macros::AutoComplete 
    7977end 
  • trunk/actionpack/lib/action_controller/macros/auto_complete.rb

    r4952 r7450  
    1 module ActionController 
    2   # Macros are class-level calls that add pre-defined actions to the controller based on the parameters passed in. 
    3   # Currently, they're used to bridge the JavaScript macros, like autocompletion and in-place editing, with the controller 
    4   # backing. 
    5   module Macros 
    6     module AutoComplete #:nodoc: 
    7       def self.included(base) #:nodoc: 
    8         base.extend(ClassMethods) 
    9       end 
    10  
    11       # DEPRECATION WARNING: This method will become a separate plugin when Rails 2.0 ships. 
    12       # 
    13       # Example: 
    14       # 
    15       #   # Controller 
    16       #   class BlogController < ApplicationController 
    17       #     auto_complete_for :post, :title 
    18       #   end 
    19       # 
    20       #   # View 
    21       #   <%= text_field_with_auto_complete :post, title %> 
    22       # 
    23       # By default, auto_complete_for limits the results to 10 entries, 
    24       # and sorts by the given field. 
    25       #  
    26       # auto_complete_for takes a third parameter, an options hash to 
    27       # the find method used to search for the records: 
    28       # 
    29       #   auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC' 
    30       # 
    31       # For help on defining text input fields with autocompletion,  
    32       # see ActionView::Helpers::JavaScriptHelper. 
    33       # 
    34       # For more examples, see script.aculo.us: 
    35       # * http://script.aculo.us/demos/ajax/autocompleter 
    36       # * http://script.aculo.us/demos/ajax/autocompleter_customized 
    37       module ClassMethods 
    38         def auto_complete_for(object, method, options = {}) 
    39           define_method("auto_complete_for_#{object}_#{method}") do 
    40             find_options = {  
    41               :conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ],  
    42               :order => "#{method} ASC", 
    43               :limit => 10 }.merge!(options) 
    44              
    45             @items = object.to_s.camelize.constantize.find(:all, find_options) 
    46  
    47             render :inline => "<%= auto_complete_result @items, '#{method}' %>" 
    48           end 
    49         end 
    50       end 
    51     end 
    52   end 
    53 end 
  • trunk/actionpack/lib/action_view/helpers/java_script_macros_helper.rb

    r7442 r7450  
    1 require 'action_view/helpers/tag_helper' 
    2  
    3 module ActionView 
    4   module Helpers 
    5     # Provides a set of helpers for creating JavaScript macros that rely on and often bundle methods from JavaScriptHelper into 
    6     # larger units. These macros also rely on counterparts in the controller that provide them with their backing. The in-place 
    7     # editing relies on ActionController::Base.in_place_edit_for and the autocompletion relies on  
    8     # ActionController::Base.auto_complete_for. 
    9     module JavaScriptMacrosHelper       
    10       # DEPRECATION WARNING: This method will become a separate plugin when Rails 2.0 ships. 
    11       # 
    12       # Adds AJAX autocomplete functionality to the text input field with the  
    13       # DOM ID specified by +field_id+. 
    14       # 
    15       # This function expects that the called action returns an HTML <ul> list, 
    16       # or nothing if no entries should be displayed for autocompletion. 
    17       # 
    18       # You'll probably want to turn the browser's built-in autocompletion off, 
    19       # so be sure to include an <tt>autocomplete="off"</tt> attribute with your text 
    20       # input field. 
    21       # 
    22       # The autocompleter object is assigned to a Javascript variable named <tt>field_id</tt>_auto_completer. 
    23       # This object is useful if you for example want to trigger the auto-complete suggestions through 
    24       # other means than user input (for that specific case, call the <tt>activate</tt> method on that object).  
    25       #  
    26       # Required +options+ are: 
    27       # <tt>:url</tt>::                  URL to call for autocompletion results 
    28       #                                  in url_for format. 
    29       #  
    30       # Addtional +options+ are: 
    31       # <tt>:update</tt>::               Specifies the DOM ID of the element whose  
    32       #                                  innerHTML should be updated with the autocomplete 
    33       #                                  entries returned by the AJAX request.  
    34       #                                  Defaults to <tt>field_id</tt> + '_auto_complete' 
    35       # <tt>:with</tt>::                 A JavaScript expression specifying the 
    36       #                                  parameters for the XMLHttpRequest. This defaults 
    37       #                                  to 'fieldname=value'. 
    38       # <tt>:frequency</tt>::            Determines the time to wait after the last keystroke 
    39       #                                  for the AJAX request to be initiated. 
    40       # <tt>:indicator</tt>::            Specifies the DOM ID of an element which will be 
    41       #                                  displayed while autocomplete is running. 
    42       # <tt>:tokens</tt>::               A string or an array of strings containing 
    43       #                                  separator tokens for tokenized incremental  
    44       #                                  autocompletion. Example: <tt>:tokens => ','</tt> would 
    45       #                                  allow multiple autocompletion entries, separated 
    46       #                                  by commas. 
    47       # <tt>:min_chars</tt>::            The minimum number of characters that should be 
    48       #                                  in the input field before an Ajax call is made 
    49       #                                  to the server. 
    50       # <tt>:on_hide</tt>::              A Javascript expression that is called when the 
    51       #                                  autocompletion div is hidden. The expression 
    52       #                                  should take two variables: element and update. 
    53       #                                  Element is a DOM element for the field, update 
    54       #                                  is a DOM element for the div from which the 
    55       #                                  innerHTML is replaced. 
    56       # <tt>:on_show</tt>::              Like on_hide, only now the expression is called 
    57       #                                  then the div is shown. 
    58       # <tt>:after_update_element</tt>:: A Javascript expression that is called when the 
    59       #                                  user has selected one of the proposed values.  
    60       #                                  The expression should take two variables: element and value. 
    61       #                                  Element is a DOM element for the field, value 
    62       #                                  is the value selected by the user. 
    63       # <tt>:select</tt>::               Pick the class of the element from which the value for  
    64       #                                  insertion should be extracted. If this is not specified, 
    65       #                                  the entire element is used. 
    66       # <tt>:method</tt>::               Specifies the HTTP verb to use when the autocompletion 
    67       #                                  request is made. Defaults to POST. 
    68       def auto_complete_field(field_id, options = {}) 
    69         function =  "var #{field_id}_auto_completer = new Ajax.Autocompleter(" 
    70         function << "'#{field_id}', " 
    71         function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', " 
    72         function << "'#{url_for(options[:url])}'" 
    73          
    74         js_options = {} 
    75         js_options[:tokens] = array_or_string_for_javascript(options[:tokens]) if options[:tokens] 
    76         js_options[:callback]   = "function(element, value) { return #{options[:with]} }" if options[:with] 
    77         js_options[:indicator]  = "'#{options[:indicator]}'" if options[:indicator] 
    78         js_options[:select]     = "'#{options[:select]}'" if options[:select] 
    79         js_options[:paramName]  = "'#{options[:param_name]}'" if options[:param_name] 
    80         js_options[:frequency]  = "#{options[:frequency]}" if options[:frequency] 
    81         js_options[:method]     = "'#{options[:method].to_s}'" if options[:method] 
    82  
    83         { :after_update_element => :afterUpdateElement,  
    84           :on_show => :onShow, :on_hide => :onHide, :min_chars => :minChars }.each do |k,v| 
    85           js_options[v] = options[k] if options[k] 
    86         end 
    87  
    88         function << (', ' + options_for_javascript(js_options) + ')') 
    89  
    90         javascript_tag(function) 
    91       end 
    92        
    93       # DEPRECATION WARNING: This method will become a separate plugin when Rails 2.0 ships. 
    94       # 
    95       # Use this method in your view to generate a return for the AJAX autocomplete requests. 
    96       # 
    97       # Example action: 
    98       # 
    99       #   def auto_complete_for_item_title 
    100       #     @items = Item.find(:all,  
    101       #       :conditions => [ 'LOWER(description) LIKE ?',  
    102       #       '%' + request.raw_post.downcase + '%' ]) 
    103       #     render :inline => "<%= auto_complete_result(@items, 'description') %>" 
    104       #   end 
    105       # 
    106       # The auto_complete_result can of course also be called from a view belonging to the  
    107       # auto_complete action if you need to decorate it further. 
    108       def auto_complete_result(entries, field, phrase = nil) 
    109         return unless entries 
    110         items = entries.map { |entry| content_tag("li", phrase ? highlight(entry[field], phrase) : h(entry[field])) } 
    111         content_tag("ul", items.uniq) 
    112       end 
    113        
    114       # DEPRECATION WARNING: This method will become a separate plugin when Rails 2.0 ships. 
    115       # 
    116       # Wrapper for text_field with added AJAX autocompletion functionality. 
    117       # 
    118       # In your controller, you'll need to define an action called 
    119       # auto_complete_for to respond the AJAX calls, 
    120       #  
    121       # See the RDoc on ActionController::Macros::AutoComplete to learn more about this. 
    122       def text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {}) 
    123         (completion_options[:skip_style] ? "" : auto_complete_stylesheet) + 
    124         text_field(object, method, tag_options) + 
    125         content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") + 
    126         auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" } }.update(completion_options)) 
    127       end 
    128  
    129       private 
    130         def auto_complete_stylesheet 
    131           content_tag('style', <<-EOT, :type => Mime::CSS) 
    132             div.auto_complete { 
    133               width: 350px; 
    134               background: #fff; 
    135             } 
    136             div.auto_complete ul { 
    137               border:1px solid #888; 
    138               margin:0; 
    139               padding:0; 
    140               width:100%; 
    141               list-style-type:none; 
    142             } 
    143             div.auto_complete ul li { 
    144               margin:0; 
    145               padding:3px; 
    146             } 
    147             div.auto_complete ul li.selected { 
    148               background-color: #ffb; 
    149             } 
    150             div.auto_complete ul strong.highlight { 
    151               color: #800;  
    152               margin:0; 
    153               padding:0; 
    154             } 
    155           EOT 
    156         end 
    157  
    158     end 
    159   end 
    160 end 
  • trunk/actionpack/test/template/java_script_macros_helper_test.rb

    r7442 r7450  
    1 require "#{File.dirname(__FILE__)}/../abstract_unit" 
    2  
    3 class JavaScriptMacrosHelperTest < Test::Unit::TestCase 
    4   include ActionView::Helpers::JavaScriptHelper 
    5   include ActionView::Helpers::JavaScriptMacrosHelper 
    6    
    7   include ActionView::Helpers::UrlHelper 
    8   include ActionView::Helpers::TagHelper 
    9   include ActionView::Helpers::TextHelper 
    10   include ActionView::Helpers::FormHelper 
    11   include ActionView::Helpers::CaptureHelper 
    12    
    13   def setup 
    14     @controller = Class.new do 
    15       def url_for(options) 
    16         url =  "http://www.example.com/" 
    17         url << options[:action].to_s if options and options[:action] 
    18         url 
    19       end 
    20     end 
    21     @controller = @controller.new 
    22   end 
    23  
    24  
    25   def test_auto_complete_field 
    26     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {})\n//]]>\n</script>), 
    27       auto_complete_field("some_input", :url => { :action => "autocomplete" }); 
    28     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:','})\n//]]>\n</script>), 
    29       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => ','); 
    30     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:[',']})\n//]]>\n</script>), 
    31       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => [',']);   
    32     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {minChars:3})\n//]]>\n</script>), 
    33       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :min_chars => 3); 
    34     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {onHide:function(element, update){alert('me');}})\n//]]>\n</script>), 
    35       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :on_hide => "function(element, update){alert('me');}"); 
    36     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {frequency:2})\n//]]>\n</script>), 
    37       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :frequency => 2); 
    38     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {afterUpdateElement:function(element,value){alert('You have chosen: '+value)}})\n//]]>\n</script>), 
    39       auto_complete_field("some_input", :url => { :action => "autocomplete" },  
    40         :after_update_element => "function(element,value){alert('You have chosen: '+value)}"); 
    41     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {paramName:'huidriwusch'})\n//]]>\n</script>), 
    42       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :param_name => 'huidriwusch'); 
    43     assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {method:'get'})\n//]]>\n</script>), 
    44       auto_complete_field("some_input", :url => { :action => "autocomplete" }, :method => :get); 
    45   end 
    46    
    47   def test_auto_complete_result 
    48     result = [ { :title => 'test1'  }, { :title => 'test2'  } ] 
    49     assert_equal %(<ul><li>test1</li><li>test2</li></ul>),  
    50       auto_complete_result(result, :title) 
    51     assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li><li>t<strong class=\"highlight\">est</strong>2</li></ul>),  
    52       auto_complete_result(result, :title, "est") 
    53      
    54     resultuniq = [ { :title => 'test1'  }, { :title => 'test1'  } ] 
    55     assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li></ul>),  
    56       auto_complete_result(resultuniq, :title, "est") 
    57   end 
    58    
    59   def test_text_field_with_auto_complete 
    60     assert_match %(<style type="text/css">), 
    61       text_field_with_auto_complete(:message, :recipient) 
    62  
    63     assert_dom_equal %(<input id=\"message_recipient\" name=\"message[recipient]\" size=\"30\" type=\"text\" /><div class=\"auto_complete\" id=\"message_recipient_auto_complete\"></div><script type=\"text/javascript\">\n//<![CDATA[\nvar message_recipient_auto_completer = new Ajax.Autocompleter('message_recipient', 'message_recipient_auto_complete', 'http://www.example.com/auto_complete_for_message_recipient', {})\n//]]>\n</script>), 
    64       text_field_with_auto_complete(:message, :recipient, {}, :skip_style => true) 
    65   end 
    66    
    67 end