From 11606a9f2f59baedaef8dc9b8cd8fbac664b2434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J.=20Pablo=20Fern=C3=A1ndez?= Date: Wed, 2 Jun 2010 19:18:41 +0200 Subject: [PATCH] Created image_button_to and image_button_to_fuction, similar to their non-image existing counterparts. --- .../lib/action_view/helpers/form_tag_helper.rb | 83 ++++++++++++++++++++ .../lib/action_view/helpers/javascript_helper.rb | 37 +++++++++ actionpack/test/template/form_tag_helper_test.rb | 58 ++++++++++++++ actionpack/test/template/javascript_helper_test.rb | 30 +++++++ 4 files changed, 208 insertions(+), 0 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 7962686..8f03b1d 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -433,6 +433,89 @@ module ActionView tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options.stringify_keys) end + # Generates a form containing a single image button that submits to the URL created + # by the set of +options+. This is the safest method to ensure image links that + # cause changes to your data are not triggered by search bots or accelerators. + # If the HTML button does not work with your layout, you can also consider + # using the +link_to+ method with the :method modifier as described in + # the +link_to+ documentation, but containing an image tag. + # + # The generated form element has a class name of image_button_to + # to allow styling of the form itself and its children. You can control + # the form submission and input element behavior using +html_options+. + # This method accepts the :method and :confirm modifiers + # described in the +link_to+ documentation. If no :method modifier + # is given, it will default to performing a POST operation. You can also + # disable the button by passing :disabled => true in +html_options+. + # If you are using RESTful routes, you can pass the :method + # to change the HTTP verb used to submit the form. + # + # ==== Options + # The +options+ hash accepts the same options as url_for. + # + # There are a few special +html_options+: + # * :method - Specifies the anchor name to be appended to the path. + # * :disabled - Specifies the anchor name to be appended to the path. + # * :confirm - This will use the unobtrusive JavaScript driver to + # prompt with the question specified. If the user accepts, the link is + # processed normally, otherwise no action is taken. + # * :remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the + # submit behaviour. By default this behaviour is an ajax submit. + # + # ==== Examples + # <%= image_button_to "new.png", :action => "new" %> + # # => "
+ # #
+ # #
" + # + # + # <%= image_button_to "delete.png", { :action => "delete", :id => @image.id }, + # :confirm => "Are you sure?", :method => :delete %> + # # => "
+ # #
+ # # + # # + # #
+ # #
" + # + # + # <%= image_button_to('destroy.png', 'http://www.example.com', :confirm => 'Are you sure?', + # :method => "delete", :remote => true, :disable_with => 'loading...') %> + # # => "
+ # #
+ # # + # # + # #
+ # #
" + # # + def image_button_to(source, options = {}, html_options = {}) + html_options = html_options.stringify_keys + convert_boolean_attributes!(html_options, %w( disabled )) + + method_tag = '' + if (method = html_options.delete('method')) && %w{put delete}.include?(method.to_s) + method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s) + end + + form_method = method.to_s == 'get' ? 'get' : 'post' + + remote = html_options.delete('remote') + + request_token_tag = '' + if form_method == 'post' && protect_against_forgery? + request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) + end + + url = options.is_a?(String) ? options : self.url_for(options) + name ||= url + + html_options = convert_options_to_data_attributes(options, html_options) + + + ("
" + + method_tag + image_submit_tag(source, html_options) + request_token_tag + "
").html_safe + end + # Creates a field set for grouping HTML form elements. # # legend will become the fieldset's title (optional as per W3C). diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index b0a7718..42f9b7a 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -122,6 +122,43 @@ module ActionView tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick)) end + # Returns an image button for the given +source+ that'll trigger a + # JavaScript +function+ using the onclick handler. + # + # The first argument +source+ is the filename of the button as treated by + # +image_submit_tag+, that is, passed to AssetTagHelper#image_path. + # + # The next arguments are optional and may include the javascript function + # definition and a hash of html_options. + # + # The +function+ argument can be omitted in favor of an +update_page+ block, + # which evaluates to a string when the template is rendered (instead of + # making an Ajax request first). + # + # The +html_options+ will accept a hash of html attributes for the link tag. + # Some examples are :class => "nav_button", :id => "articles_nav_button" + # + # Note: if you choose to specify the javascript function in a block, but + # would like to pass html_options, set the +function+ parameter to nil + # + # Examples: + # button_to_function "greeting.png", "alert('Hello world!')" + # button_to_function "delete.png", "if (confirm('Really?')) do_delete()" + # button_to_function "details.png" do |page| + # page[:details].visual_effect :toggle_slide + # end + # button_to_function "details.png", :class => "details_button" do |page| + # page[:details].visual_effect :toggle_slide + # end + def image_button_to_function(source, *args, &block) + html_options = args.extract_options!.symbolize_keys + + function = block_given? ? update_page(&block) : args[0] || '' + onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};" + + image_submit_tag(source, html_options.merge({:onclick => onclick})) + end + # Returns a link of the given +name+ that will trigger a JavaScript +function+ using the # onclick handler and return false after the fact. # diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index b75863b..fd261be 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -358,6 +358,64 @@ class FormTagHelperTest < ActionView::TestCase ) end + def test_image_button_to_with_straight_url + assert_dom_equal "
", image_button_to("hello.png", "http://www.example.com") + end + + def test_image_button_to_with_query + assert_dom_equal "
", image_button_to("hello.png", "http://www.example.com/q1=v1&q2=v2") + end + + def test_image_button_to_with_escaped_query + assert_dom_equal "
", image_button_to("hello.png", "http://www.example.com/q1=v1&q2=v2") + end + + def test_image_button_to_with_javascript_confirm + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :confirm => "Are you sure?") + ) + end + + def test_image_button_to_with_remote_and_javascript_confirm + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :remote => true, :confirm => "Are you sure?") + ) + end + + def test_image_button_to_with_remote_false + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :remote => false) + ) + end + + def test_image_button_to_enabled_disabled + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :disabled => false) + ) + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :disabled => true) + ) + end + + def test_image_button_to_with_method_delete + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :method => :delete) + ) + end + + def test_image_button_to_with_method_get + assert_dom_equal( + "
", + image_button_to("hello.png", "http://www.example.com", :method => :get) + ) + end + def test_search_field_tag expected = %{} assert_dom_equal(expected, search_field_tag("query")) diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index c5c2a6b..7651877 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -14,6 +14,7 @@ class JavaScriptHelperTest < ActionView::TestCase def setup super + @controller = BasicController.new ActiveSupport.escape_html_entities_in_json = true @template = self end @@ -60,6 +61,35 @@ class JavaScriptHelperTest < ActionView::TestCase button_to_function("Greeting") end + def test_image_button_to_function + assert_dom_equal %(), + image_button_to_function("greeting.png", "alert('Hello world!')") + end + + def test_image_button_to_function_with_rjs_block + html = image_button_to_function( "greeting.png" ) do |page| + page.replace_html 'header', "

Greetings

" + end + assert_dom_equal %(), html + end + + def test_image_button_to_function_with_rjs_block_and_options + html = image_button_to_function( "greeting.png", :class => "greeter" ) do |page| + page.replace_html 'header', "

Greetings

" + end + assert_dom_equal %(), html + end + + def test_image_button_to_function_with_onclick + assert_dom_equal "", + image_button_to_function("greeting.png", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')") + end + + def test_image_button_to_function_without_function + assert_dom_equal "", + image_button_to_function("greeting.png") + end + def test_link_to_function assert_dom_equal %(Greeting), link_to_function("Greeting", "alert('Hello world!')") -- 1.7.1