diff options
Diffstat (limited to 'actionpack/lib/action_view/helpers')
16 files changed, 127 insertions, 87 deletions
diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 87b7adf6c4..e106bb0897 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -6,7 +6,7 @@ require 'active_support/core_ext/kernel/reporting' module ActionView class Base - @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe! } + @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe } cattr_accessor :field_error_proc end @@ -86,12 +86,11 @@ module ActionView submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil) - contents << hidden_field(record_name, :id) unless record.new_record? - contents << all_input_tags(record, record_name, options) + contents.safe_concat hidden_field(record_name, :id) unless record.new_record? + contents.safe_concat all_input_tags(record, record_name, options) yield contents if block_given? - contents << submit_tag(submit_value) - contents << '</form>' - contents.html_safe! + contents.safe_concat submit_tag(submit_value) + contents.safe_concat('</form>') end # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 4df99f8293..96976ce45f 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -293,7 +293,7 @@ module ActionView else sources = expand_javascript_sources(sources, recursive) ensure_javascript_sources!(sources) if cache - sources.collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe! + sources.collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe end end @@ -444,7 +444,7 @@ module ActionView else sources = expand_stylesheet_sources(sources, recursive) ensure_stylesheet_sources!(sources) if cache - sources.collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe! + sources.collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe end end @@ -588,7 +588,7 @@ module ActionView if sources.is_a?(Array) content_tag("video", options) do - sources.map { |source| tag("source", :src => source) }.join.html_safe! + sources.map { |source| tag("source", :src => source) }.join.html_safe end else options[:src] = path_to_video(sources) diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index b62df75dbb..8c48300ed3 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -143,7 +143,7 @@ module ActionView # Defaults to a new empty string. def with_output_buffer(buf = nil) #:nodoc: unless buf - buf = ActionView::SafeBuffer.new + buf = ActiveSupport::SafeBuffer.new buf.force_encoding(output_buffer.encoding) if buf.respond_to?(:force_encoding) end self.output_buffer, old_buffer = buf, output_buffer diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 34f38b0a8a..8be2f76bd6 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -616,7 +616,7 @@ module ActionView build_selects_from_types(order) else - "#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe! + "#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe end end @@ -835,7 +835,7 @@ module ActionView select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt] select_html << select_options_as_html.to_s - (content_tag(:select, select_html, select_options) + "\n").html_safe! + (content_tag(:select, select_html, select_options) + "\n").html_safe end # Builds a prompt option tag with supplied options or from default options @@ -865,7 +865,7 @@ module ActionView :id => input_id_from_type(type), :name => input_name_from_type(type), :value => value - }) + "\n").html_safe! + }) + "\n").html_safe end # Returns the name attribute for the input tag @@ -896,7 +896,7 @@ module ActionView separator = separator(type) unless type == order.first # don't add on last field select.insert(0, separator.to_s + send("select_#{type}").to_s) end - select.html_safe! + select.html_safe end # Returns the separator for a given datetime component @@ -916,15 +916,15 @@ module ActionView class InstanceTag #:nodoc: def to_date_select_tag(options = {}, html_options = {}) - datetime_selector(options, html_options).select_date.html_safe! + datetime_selector(options, html_options).select_date.html_safe end def to_time_select_tag(options = {}, html_options = {}) - datetime_selector(options, html_options).select_time.html_safe! + datetime_selector(options, html_options).select_time.html_safe end def to_datetime_select_tag(options = {}, html_options = {}) - datetime_selector(options, html_options).select_datetime.html_safe! + datetime_selector(options, html_options).select_datetime.html_safe end private diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb index 885945fde3..e637dc1474 100644 --- a/actionpack/lib/action_view/helpers/debug_helper.rb +++ b/actionpack/lib/action_view/helpers/debug_helper.rb @@ -27,10 +27,10 @@ module ActionView def debug(object) begin Marshal::dump(object) - "<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", " ")}</pre>".html_safe! + "<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", " ")}</pre>".html_safe rescue Exception => e # errors from Marshal or YAML # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback - "<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe! + "<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe end end end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 157deebe40..1d91b6957a 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -225,6 +225,33 @@ module ActionView # ... # <% end %> # + # === Unobtrusive JavaScript + # + # Specifying: + # + # :remote => true + # + # in the options hash creates a form that will allow the unobtrusive JavaScript drivers to modify its + # behaviour. The expected default behaviour is an XMLHttpRequest in the background instead of the regular + # POST arrangement, but ultimately the behaviour is the choice of the JavaScript driver implementor. + # Even though it's using JavaScript to serialize the form elements, the form submission will work just like + # a regular submission as viewed by the receiving side (all elements available in <tt>params</tt>). + # + # Example: + # + # <% form_for(:post, @post, :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| %> + # ... + # <% end %> + # + # The HTML generated for this would be: + # + # <form action='http://www.example.com' id='create-post' method='post' data-remote='true'> + # <div style='margin:0;padding:0;display:inline'> + # <input name='_method' type='hidden' value='put' /> + # </div> + # ... + # </form> + # # === Customized form builders # # You can also build forms using a customized FormBuilder class. Subclass @@ -280,9 +307,11 @@ module ActionView args.unshift object end + options[:html][:remote] = true if options.delete(:remote) + concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {})) fields_for(object_name, *(args << options), &proc) - concat('</form>'.html_safe!) + safe_concat('</form>') end def apply_form_for_options!(object_or_array, options) #:nodoc: @@ -850,7 +879,7 @@ module ActionView end hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value) checkbox = tag("input", options) - (hidden + checkbox).html_safe! + (hidden + checkbox).html_safe end def to_boolean_select_tag(options = {}) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index d3e614b98f..21acfbbee8 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -296,7 +296,7 @@ module ActionView options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}>#{html_escape(text.to_s)}</option>) end - options_for_select.join("\n").html_safe! + options_for_select.join("\n").html_safe end # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index fb32f78e5b..9b8471c6c6 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -19,6 +19,8 @@ module ActionView # If "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt> # is added to simulate the verb over post. # * A list of parameters to feed to the URL the form will be posted to. + # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the + # submit behaviour. By default this behaviour is an ajax submit. # # ==== Examples # form_tag('/posts') @@ -30,10 +32,14 @@ module ActionView # form_tag('/upload', :multipart => true) # # => <form action="/upload" method="post" enctype="multipart/form-data"> # - # <% form_tag '/posts' do -%> + # <% form_tag('/posts')do -%> # <div><%= submit_tag 'Save' %></div> # <% end -%> # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form> + # + # <% form_tag('/posts', :remote => true) %> + # # => <form action="/posts" method="post" data-remote="true"> + # def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block) html_options = html_options_for_form(url_for_options, options, *parameters_for_url) if block_given? @@ -333,12 +339,13 @@ module ActionView # Creates a submit button with the text <tt>value</tt> as the caption. # # ==== Options - # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm - # prompt with the question specified. If the user accepts, the form is - # processed normally, otherwise no action is taken. + # * <tt>:confirm => 'question?'</tt> - If present the unobtrusive JavaScript + # drivers will provide a prompt with the question specified. If the user accepts, + # the form is processed normally, otherwise no action is taken. # * <tt>:disabled</tt> - If true, the user will not be able to use this input. - # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version - # of the submit button when the form is submitted. + # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a + # disabled version of the submit button when the form is submitted. This feature is + # provided by the unobtrusive JavaScript driver. # * Any other key creates standard HTML options for the tag. # # ==== Examples @@ -351,16 +358,22 @@ module ActionView # submit_tag "Save edits", :disabled => true # # => <input disabled="disabled" name="commit" type="submit" value="Save edits" /> # + # # submit_tag "Complete sale", :disable_with => "Please wait..." - # # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();" + # # => <input name="commit" data-disable-with="Please wait..." # # type="submit" value="Complete sale" /> # # submit_tag nil, :class => "form_submit" # # => <input class="form_submit" name="commit" type="submit" /> # # submit_tag "Edit", :disable_with => "Editing...", :class => "edit-button" - # # => <input class="edit-button" onclick="this.disabled=true;this.value='Editing...';this.form.submit();" + # # => <input class="edit-button" data-disable_with="Editing..." # # name="commit" type="submit" value="Edit" /> + # + # submit_tag "Save", :confirm => "Are you sure?" + # # => <input name='commit' type='submit' value='Save' + # data-confirm="Are you sure?" /> + # def submit_tag(value = "Save changes", options = {}) options.stringify_keys! @@ -433,7 +446,7 @@ module ActionView concat(tag(:fieldset, options, true)) concat(content_tag(:legend, legend)) unless legend.blank? concat(content) - concat("</fieldset>".html_safe!) + safe_concat("</fieldset>") end private @@ -441,6 +454,7 @@ module ActionView returning options.stringify_keys do |html_options| html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart") html_options["action"] = url_for(url_for_options, *parameters_for_url) + html_options["data-remote"] = true if html_options.delete("remote") end end @@ -460,14 +474,14 @@ module ActionView def form_tag_html(html_options) extra_tags = extra_tags_for_form(html_options) - (tag(:form, html_options, true) + extra_tags).html_safe! + (tag(:form, html_options, true) + extra_tags).html_safe end def form_tag_in_block(html_options, &block) content = capture(&block) concat(form_tag_html(html_options)) concat(content) - concat("</form>".html_safe!) + safe_concat("</form>") end def token_tag diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 64b71663c3..3d3502a08b 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -92,7 +92,7 @@ module ActionView :precision => precision, :delimiter => delimiter, :separator => separator) - ).gsub(/%u/, unit).html_safe! + ).gsub(/%u/, unit).html_safe rescue number end diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index d335d89274..7eb6bceca0 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -610,7 +610,7 @@ module ActionView # page.hide 'spinner' # end def update_page(&block) - JavaScriptGenerator.new(@template, &block).to_s.html_safe! + JavaScriptGenerator.new(@template, &block).to_s.html_safe end # Works like update_page but wraps the generated JavaScript in a <script> diff --git a/actionpack/lib/action_view/helpers/raw_output_helper.rb b/actionpack/lib/action_view/helpers/raw_output_helper.rb index 79b0e4ee75..8c7f41177d 100644 --- a/actionpack/lib/action_view/helpers/raw_output_helper.rb +++ b/actionpack/lib/action_view/helpers/raw_output_helper.rb @@ -2,7 +2,7 @@ module ActionView #:nodoc: module Helpers #:nodoc: module RawOutputHelper def raw(stringish) - stringish.to_s.html_safe! + stringish.to_s.html_safe end end end diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index 657d26f0a2..28e40f8560 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -50,11 +50,7 @@ module ActionView # confuse browsers. # def sanitize(html, options = {}) - returning self.class.white_list_sanitizer.sanitize(html, options) do |sanitized| - if sanitized - sanitized.html_safe! - end - end + self.class.white_list_sanitizer.sanitize(html, options).try(:html_safe) end # Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute. @@ -77,11 +73,7 @@ module ActionView # strip_tags("<div id='top-bar'>Welcome to my website!</div>") # # => Welcome to my website! def strip_tags(html) - returning self.class.full_sanitizer.sanitize(html) do |sanitized| - if sanitized - sanitized.html_safe! - end - end + self.class.full_sanitizer.sanitize(html).try(:html_safe) end # Strips all link tags from +text+ leaving just the link text. diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index ceddbd8cc1..ed80e07c78 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -1,4 +1,3 @@ -require 'action_view/erb/util' require 'set' module ActionView @@ -41,7 +40,7 @@ module ActionView # tag("img", { :src => "open & shut.png" }, false, false) # # => <img src="open & shut.png" /> def tag(name, options = nil, open = false, escape = true) - "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe! + "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe end # Returns an HTML block tag of type +name+ surrounding the +content+. Add @@ -94,7 +93,7 @@ module ActionView # cdata_section(File.read("hello_world.txt")) # # => <![CDATA[<hello from a text file]]> def cdata_section(content) - "<![CDATA[#{content}]]>".html_safe! + "<![CDATA[#{content}]]>".html_safe end # Returns an escaped version of +html+ without affecting existing escaped entities. @@ -128,7 +127,7 @@ module ActionView def content_tag_string(name, content, options, escape = true) tag_options = tag_options(options, escape) if options - "<#{name}#{tag_options}>#{content}</#{name}>".html_safe! + "<#{name}#{tag_options}>#{content}</#{name}>".html_safe end def tag_options(options, escape = true) @@ -143,7 +142,7 @@ module ActionView attrs << %(#{key}="#{final_value}") end end - " #{attrs.sort * ' '}".html_safe! unless attrs.empty? + " #{attrs.sort * ' '}".html_safe unless attrs.empty? end end end diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 814d86812d..412e0c82cb 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -24,14 +24,14 @@ module ActionView # end # # will either display "Logged in!" or a login link # %> - def concat(string, unused_binding = nil) - if unused_binding - ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.", caller) - end - + def concat(string) output_buffer << string end + def safe_concat(string) + output_buffer.safe_concat(string) + end + # Truncates a given +text+ after a given <tt>:length</tt> if +text+ is longer than <tt>:length</tt> # (defaults to 30). The last characters will be replaced with the <tt>:omission</tt> (defaults to "...") # for a total length not exceeding <tt>:length</tt>. diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index ad18339c60..c348ea7a0d 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -12,7 +12,7 @@ module ActionView # prepend the key with a period, nothing is converted. def translate(key, options = {}) options[:raise] = true - I18n.translate(scope_key_by_partial(key), options).html_safe! + I18n.translate(scope_key_by_partial(key), options).html_safe rescue I18n::MissingTranslationData => e keys = I18n.send(:normalize_translation_keys, e.locale, e.key, e.options[:scope]) content_tag('span', keys.join(', '), :class => 'translation_missing') diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index bd179ef0b3..168a3bdbc0 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -98,7 +98,7 @@ module ActionView polymorphic_path(options) end - escape ? escape_once(url).html_safe! : url + escape ? escape_once(url).html_safe : url end # Creates a link tag of the given +name+ using a URL created by the set @@ -117,8 +117,8 @@ module ActionView # end # # ==== Options - # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm - # prompt with the question specified. If the user accepts, the link is + # * <tt>:confirm => 'question?'</tt> - This will allow the unobtrusive JavaScript + # driver to prompt with the question specified. If the user accepts, the link is # processed normally, otherwise no action is taken. # * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically # create an HTML form and immediately submit the form for processing using @@ -195,23 +195,20 @@ module ActionView # link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux") # # => <a href="/searches?foo=bar&baz=quux">Nonsense search</a> # - # The three options specific to +link_to+ (<tt>:confirm</tt> and <tt>:method</tt>) are used as follows: + # The two options specific to +link_to+ (<tt>:confirm</tt> and <tt>:method</tt>) are used as follows: # # link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?" - # # => <a href="http://www.rubyonrails.org/" onclick="return confirm('Are you sure?');">Visit Other Site</a> - # - # link_to "Delete Image", @image, :confirm => "Are you sure?", :method => :delete - # # => <a href="/images/9" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); - # f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; - # var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); - # m.setAttribute('value', 'delete');var s = document.createElement('input'); s.setAttribute('type', 'hidden'); - # s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'Q/ttlxPYZ6R77B+vZ1sBkhj21G2isO9dpE6UtOHBApg='); - # f.appendChild(s)f.appendChild(m);f.submit(); };return false;">Delete Image</a> + # # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?"">Visit Other Site</a> + # + # link_to("Destroy", "http://www.example.com", :method => :delete, :confirm => "Are you sure?") + # # => <a href='http://www.example.com' rel="nofollow" data-method="delete" data-confirm="Are you sure?">Destroy</a> + + # def link_to(*args, &block) if block_given? options = args.first || {} html_options = args.second - concat(link_to(capture(&block), options, html_options).html_safe!) + safe_concat(link_to(capture(&block), options, html_options)) else name = args[0] options = args[1] || {} @@ -229,7 +226,7 @@ module ActionView end href_attr = "href=\"#{url}\"" unless href - "<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe! + "<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe end end @@ -256,9 +253,11 @@ module ActionView # There are a few special +html_options+: # * <tt>:method</tt> - Specifies the anchor name to be appended to the path. # * <tt>:disabled</tt> - Specifies the anchor name to be appended to the path. - # * <tt>:confirm</tt> - This will add a JavaScript confirm + # * <tt>:confirm</tt> - 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. + # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the + # submit behaviour. By default this behaviour is an ajax submit. # # ==== Examples # <%= button_to "New", :action => "new" %> @@ -266,15 +265,27 @@ module ActionView # # <div><input value="New" type="submit" /></div> # # </form>" # - # button_to "Delete Image", { :action => "delete", :id => @image.id }, - # :confirm => "Are you sure?", :method => :delete + # + # <%= button_to "Delete Image", { :action => "delete", :id => @image.id }, + # :confirm => "Are you sure?", :method => :delete %> # # => "<form method="post" action="/images/delete/1" class="button-to"> # # <div> # # <input type="hidden" name="_method" value="delete" /> - # # <input onclick="return confirm('Are you sure?');" - # # value="Delete" type="submit" /> + # # <input data-confirm='Are you sure?' value="Delete" type="submit" /> # # </div> # # </form>" + # + # + # <%= button_to('Destroy', 'http://www.example.com', :confirm => 'Are you sure?', + # :method => "delete", :remote => true, :disable_with => 'loading...') %> + # # => "<form class='button-to' method='post' action='http://www.example.com' data-remote='true'> + # # <div> + # # <input name='_method' value='delete' type='hidden' /> + # # <input value='Destroy' type='submit' disable_with='loading...' data-confirm='Are you sure?' /> + # # </div> + # # </form>" + # # + def button_to(name, options = {}, html_options = {}) html_options = html_options.stringify_keys convert_boolean_attributes!(html_options, %w( disabled )) @@ -286,6 +297,8 @@ module ActionView 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) @@ -298,8 +311,8 @@ module ActionView html_options.merge!("type" => "submit", "value" => name) - ("<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" + - method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe! + ("<form method=\"#{form_method}\" action=\"#{escape_once url}\" #{"data-remote=\"true\"" if remote} class=\"button-to\"><div>" + + method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe end @@ -565,14 +578,8 @@ module ActionView method, href = html_options.delete("method"), html_options['href'] - if confirm && method - add_confirm_to_attributes!(html_options, confirm) - add_method_to_attributes!(html_options, method) - elsif confirm - add_confirm_to_attributes!(html_options, confirm) - elsif method - add_method_to_attributes!(html_options, method) - end + add_confirm_to_attributes!(html_options, confirm) if confirm + add_method_to_attributes!(html_options, method) if method html_options["data-url"] = options[:url] if options.is_a?(Hash) && options[:url] |