From 2dc1402417242784a738321e7edd521f8ec7ac83 Mon Sep 17 00:00:00 2001 From: pleax Date: Sat, 15 May 2010 13:53:59 +0400 Subject: added support for html attributes in options_for_select [#2165] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../lib/action_view/helpers/form_options_helper.rb | 27 ++++++++++- .../test/template/form_options_helper_test.rb | 56 ++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 8f8db548c3..fe71d2cdf7 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -270,6 +270,15 @@ module ActionView # options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"]) # \n\n # + # You can optionally provide html attributes as the last element of the array. + # + # Examples: + # options_for_select([ "Denmark", ["USA", {:class=>'bold'}], "Sweden" ], ["USA", "Sweden"]) + # \n\n + # + # options_for_select([["Dollar", "$", {:class=>"bold"}], ["Kroner", "DKK", {:onclick => "alert('HI');"}]]) + # \n + # # If you wish to specify disabled option tags, set +selected+ to be a hash, with :disabled being either a value # or array of values to be disabled. In this case, you can use :selected to specify selected option tags. # @@ -291,10 +300,11 @@ module ActionView selected, disabled = extract_selected_and_disabled(selected) options_for_select = container.inject([]) do |options, element| + html_attributes = option_html_attributes(element) text, value = option_text_and_value(element) selected_attribute = ' selected="selected"' if option_value_selected?(value, selected) disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled) - options << %() + options << %() end options_for_select.join("\n").html_safe @@ -486,9 +496,22 @@ module ActionView end private + def option_html_attributes(element) + return "" unless Array === element + html_attributes = [] + element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v| + html_attributes << " #{k}=\"#{html_escape(v.to_s)}\"" + end + html_attributes.join + end + def option_text_and_value(option) # Options are [text, value] pairs or strings used for both. - if !option.is_a?(String) and option.respond_to?(:first) and option.respond_to?(:last) + case + when Array === option + option = option.reject { |e| Hash === e } + [option.first, option.last] + when !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last) [option.first, option.last] else [option, option] diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 98503c32fd..19b73aa810 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -767,6 +767,62 @@ class FormOptionsHelperTest < ActionView::TestCase html end + def test_options_for_select_with_element_attributes + assert_dom_equal( + "\n\n\n", + options_for_select([ [ "", { :class => 'bold' } ], [ "USA", { :onclick => "alert('Hello World');" } ], [ "Sweden" ], "Germany" ]) + ) + end + + def test_options_for_select_with_element_attributes_and_selection + assert_dom_equal( + "\n\n", + options_for_select([ "", [ "USA", { :class => 'bold' } ], "Sweden" ], "USA") + ) + end + + def test_options_for_select_with_element_attributes_and_selection_array + assert_dom_equal( + "\n\n", + options_for_select([ "", [ "USA", { :class => 'bold' } ], "Sweden" ], [ "USA", "Sweden" ]) + ) + end + + def test_option_html_attributes_from_without_hash + assert_dom_equal( + "", + option_html_attributes([ 'foo', 'bar' ]) + ) + end + + def test_option_html_attributes_with_single_element_hash + assert_dom_equal( + " class=\"fancy\"", + option_html_attributes([ 'foo', 'bar', { :class => 'fancy' } ]) + ) + end + + def test_option_html_attributes_with_multiple_element_hash + assert_dom_equal( + " class=\"fancy\" onclick=\"alert('Hello World');\"", + option_html_attributes([ 'foo', 'bar', { :class => 'fancy', 'onclick' => "alert('Hello World');" } ]) + ) + end + + def test_option_html_attributes_with_multiple_hashes + assert_dom_equal( + " class=\"fancy\" onclick=\"alert('Hello World');\"", + option_html_attributes([ 'foo', 'bar', { :class => 'fancy' }, { 'onclick' => "alert('Hello World');" } ]) + ) + end + + def test_option_html_attributes_with_special_characters + assert_dom_equal( + " onclick=\"alert("<code>")\"", + option_html_attributes([ 'foo', 'bar', { :onclick => %(alert("")) } ]) + ) + end + def test_grouped_collection_select @continents = [ Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ), -- cgit v1.2.3