From 8a46e1182e3fce36aee5e6cb65737c4e755bbced Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Fri, 29 Jan 2010 14:03:38 -0600
Subject: Add rails.js driver to default source list

---
 actionpack/lib/action_view/helpers/asset_tag_helper.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 83357dd76f..4df99f8293 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -140,7 +140,7 @@ module ActionView
         :stylesheets_dir => "#{assets_dir}/stylesheets",
       }
 
-      JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
+      JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
 
       # Returns a link tag that browsers and news readers can use to auto-detect
       # an RSS or ATOM feed. The +type+ can either be <tt>:rss</tt> (default) or
-- 
cgit v1.2.3


From bddd1bb6268e8ac2142c8d8c738929d2f2e8447a Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Fri, 29 Jan 2010 20:00:55 -0600
Subject: Deprecate link_to :popup

---
 .../lib/action_view/helpers/javascript_helper.rb      | 19 ++++++-------------
 actionpack/lib/action_view/helpers/url_helper.rb      | 18 ++----------------
 2 files changed, 8 insertions(+), 29 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index ee6481b86d..02d0a88189 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -189,24 +189,21 @@ module ActionView
 
     protected
       def convert_options_to_javascript!(html_options, url = '')
-        confirm, popup = html_options.delete("confirm"), html_options.delete("popup")
+        confirm = html_options.delete("confirm")
+
+        if html_options.key?("popup")
+          ActiveSupport::Deprecation.warn(":popup has been deprecated", caller)
+        end
 
         method, href = html_options.delete("method"), html_options['href']
 
-        if popup && method
-          raise ActionView::ActionViewError, "You can't use :popup and :method in the same link"
-        elsif confirm && popup
-          add_confirm_to_attributes!(html_options, confirm)
-          html_options["data-popup"] = popup_attributes(popup)
-        elsif confirm && method
+        if confirm && method
           add_confirm_to_attributes!(html_options, confirm)
           add_method_to_attributes!(html_options, method, url)
         elsif confirm
           add_confirm_to_attributes!(html_options, confirm)
         elsif method
           add_method_to_attributes!(html_options, method, url)
-        elsif popup
-          html_options["data-popup"] = popup_attributes(popup)
         end
       end
 
@@ -226,10 +223,6 @@ module ActionView
           html_options["data-disable-with"] = disable_with if disable_with
       end
 
-      def popup_attributes(popup)
-        popup.is_a?(Array) ? "{title: '#{popup.first}', options: '#{popup.last}'}" : "true"
-      end
-
       def options_for_javascript(options)
         if options.empty?
           '{}'
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 4424dbba42..837dca6149 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -120,10 +120,6 @@ module ActionView
       # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm
       #   prompt with the question specified. If the user accepts, the link is
       #   processed normally, otherwise no action is taken.
-      # * <tt>:popup => true || array of window options</tt> - This will force the
-      #   link to open in a popup window. By passing true, a default browser window
-      #   will be opened with the URL. You can also specify an array of options
-      #   that are passed to the <tt>window.open</tt> JavaScript call.
       # * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically
       #   create an HTML form and immediately submit the form for processing using
       #   the HTTP verb specified. Useful for having links perform a POST operation
@@ -136,10 +132,6 @@ module ActionView
       #   the request object's methods for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>.
       # * The +html_options+ will accept a hash of html attributes for the link tag.
       #
-      # You can mix and match the +html_options+ with the exception of
-      # <tt>:popup</tt> and <tt>:method</tt> which will raise an
-      # <tt>ActionView::ActionViewError</tt> exception.
-      #
       # ==== Examples
       # Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
       # and newer RESTful routes.  Current Rails style favors RESTful routes whenever possible, so base
@@ -203,17 +195,11 @@ module ActionView
       #   link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux")
       #   # => <a href="/searches?foo=bar&amp;baz=quux">Nonsense search</a>
       #
-      # The three options specific to +link_to+ (<tt>:confirm</tt>, <tt>:popup</tt>, and <tt>:method</tt>) are used as follows:
+      # The three 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 "Help", { :action => "help" }, :popup => true
-      #   # => <a href="/testing/help/" onclick="window.open(this.href);return false;">Help</a>
-      #
-      #   link_to "View Image", @image, :popup => ['new_window_name', 'height=300,width=600']
-      #   # => <a href="/images/9" onclick="window.open(this.href,'new_window_name','height=300,width=600');return false;">View Image</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;
@@ -308,7 +294,7 @@ module ActionView
 
         url = options.is_a?(String) ? options : self.url_for(options)
         name ||= url
-     
+
         convert_options_to_javascript!(html_options, url)
 
         html_options.merge!("type" => "submit", "value" => name)
-- 
cgit v1.2.3


From ac20f2cea15844b5cc06bdfefbb410fc55ba5caf Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 14:22:39 -0600
Subject: Revert "Add rails.js driver to default source list"

This reverts commit 8a46e1182e3fce36aee5e6cb65737c4e755bbced.
---
 actionpack/lib/action_view/helpers/asset_tag_helper.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 4df99f8293..83357dd76f 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -140,7 +140,7 @@ module ActionView
         :stylesheets_dir => "#{assets_dir}/stylesheets",
       }
 
-      JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
+      JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
 
       # Returns a link tag that browsers and news readers can use to auto-detect
       # an RSS or ATOM feed. The +type+ can either be <tt>:rss</tt> (default) or
-- 
cgit v1.2.3


From 4f7a85d2c66f100f83e2fe264e1f03bf079f13dc Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 14:39:41 -0600
Subject: Revert "Merge branch 'rails/master' into ujs"

This reverts commit 3aa1ea1ae4baa4a03d03644e798eeb98a4745785, reversing
changes made to 2c12a71378d2146c822acb389b00b866f6420ff5.

Conflicts:

	actionpack/lib/action_view/helpers/javascript_helper.rb
	actionpack/lib/action_view/helpers/url_helper.rb
	actionpack/test/template/url_helper_test.rb
---
 actionpack/lib/action_view/helpers/ajax_helper.rb  | 735 ++-------------------
 actionpack/lib/action_view/helpers/form_helper.rb  |  36 +-
 .../lib/action_view/helpers/form_tag_helper.rb     |  20 +-
 .../lib/action_view/helpers/javascript_helper.rb   |  63 +-
 .../lib/action_view/helpers/prototype_helper.rb    | 449 ++++++++++++-
 actionpack/lib/action_view/helpers/url_helper.rb   |  45 ++
 6 files changed, 581 insertions(+), 767 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/ajax_helper.rb b/actionpack/lib/action_view/helpers/ajax_helper.rb
index 169a803848..9cc2acc239 100644
--- a/actionpack/lib/action_view/helpers/ajax_helper.rb
+++ b/actionpack/lib/action_view/helpers/ajax_helper.rb
@@ -1,713 +1,68 @@
 module ActionView
   module Helpers
     module AjaxHelper
-      # Included for backwards compatibility / RJS functionality
-      # Rails classes should not be aware of individual JS frameworks
-      include PrototypeHelper 
-
-      # Returns a form that will allow the unobtrusive JavaScript drivers to submit the 
-      # form dynamically. The default driver behaviour is an XMLHttpRequest in the background
-      # instead of the regular POST arrangement. 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>). The options 
-      # for specifying the target with <tt>:url</tt> anddefining callbacks is the same as +link_to_remote+.
-      #
-      # === Resource
-      #
-      # Example:
-      #
-      #   # Generates:
-      #   #     <form action='/authors' 
-      #   #           data-remote='true'
-      #   #           class='new_author' 
-      #   #           id='create-author' 
-      #   #           method='post'> ... </form>
-      #   #
-      #   <% remote_form_for(@record, {:html => { :id => 'create-author' }}) do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # This will expand to be the same as:
-      #
-      #   <% remote_form_for :post, @post, :url => post_path(@post), 
-      #                                    :html => { :method => :put, 
-      #                                               :class => "edit_post", 
-      #                                               :id => "edit_post_45" } do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # === Nested Resource
-      #
-      # Example:
-      #   # Generates:
-      #   #     <form action='/authors/1/articles' 
-      #   #           data-remote="true" 
-      #   #           class='new_article' 
-      #   #           method='post' 
-      #   #           id='new_article'></form>
-      #   #
-      #   <% remote_form_for([@author, @article]) do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # This will expand to be the same as:
-      #
-      #   <% remote_form_for :article, @article, :url => author_article_path(@author, @article), 
-      #                                          :html => { :method => :put, 
-      #                                                     :class  => "new_article", 
-      #                                                     :id     => "new_comment" } do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # If you don't need to attach a form to a resource, then check out form_remote_tag.
-      #
-      # See FormHelper#form_for for additional semantics.
-      def remote_form_for(record_or_name_or_array, *args, &proc)
-        options = args.extract_options!
-
-        if confirm = options.delete(:confirm)
-          add_confirm_to_attributes!(options, confirm)
-        end
-
-        object_name = extract_object_name_for_form!(args, options, record_or_name_or_array)
-
-        concat(form_remote_tag(options))
-        fields_for(object_name, *(args << options), &proc)
-        concat('</form>'.html_safe!)
-      end
-      alias_method :form_remote_for, :remote_form_for
-
-      # Returns a form tag that will allow the unobtrusive JavaScript drivers to submit the 
-      # form dynamically. The default JavaScript driver behaviour is an XMLHttpRequest 
-      # in the background instead of the regular POST arrangement. 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>). The options for specifying the target with <tt>:url</tt> and 
-      # defining callbacks is the same as +link_to_remote+.
-      #
-      # A "fall-through" target for browsers that doesn't do JavaScript can be
-      # specified with the <tt>:action</tt>/<tt>:method</tt> options on <tt>:html</tt>.
-      #
-      # Example:
-      #
-      #   # Generates:
-      #   #     <form action="http://www.example.com/fast" 
-      #   #           method="post" 
-      #   #           data-remote="true" 
-      #   #           data-update-success="glass_of_beer"></form>
-      #   #
-      #   form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }) {}
-      #
-      # The Hash passed to the <tt>:html</tt> key is equivalent to the options (2nd)
-      # argument in the FormTagHelper.form_tag method.
-      #
-      # By default the fall-through action is the same as the one specified in
-      # the <tt>:url</tt> (and the default method is <tt>:post</tt>).
-      #
-      # form_remote_tag also takes a block, like form_tag:
-      #   # Generates:
-      #   #     <form action='/posts'
-      #   #           method='post'
-      #   #           data-remote='true'> 
-      #   #       <input name="commit" type="submit" value="Save" />
-      #   #     </form>
-      #   #
-      #   <% form_remote_tag :url => '/posts' do -%>
-      #     <%= submit_tag 'Save' %>
-      #   <% end -%>
-      #
-      #   # Generates:
-      #   #     <form action="http://www.example.com/fast" 
-      #   #           method="post" 
-      #   #           data-remote="true" 
-      #   #           data-update-success="glass_of_beer">Hello world!</form>
-      #   #
-      #   <% form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }) do -%>
-      #     "Hello world!" 
-      #   <% end -%>
-      #
-      def form_remote_tag(options = {}, &block)
-        html_options = options.delete(:callbacks)
-
-        attributes = {}
-        attributes.merge!(extract_remote_attributes!(options))
-        attributes.merge!(html_options) if html_options
-        attributes.merge!(options)
-        attributes.delete(:builder)
-
-        form_tag(attributes.delete(:action) || attributes.delete("data-url"), attributes, &block)
-      end
-
-      # Returns a link that will allow unobtrusive JavaScript to dynamical adjust its
-      # behaviour. The default behaviour is an XMLHttpRequest in the background instead 
-      # of the regular GET arrangement. The result of that request  can then be inserted 
-      # into a DOM object whose id can be specified with <tt>options[:update]</tt>. Usually, 
-      # the result would be a partial prepared by the controller with render :partial.
-      #
-      # Examples:
-      #
-      #   # Generates:
-      #   #     <a href="#" 
-      #   #        data-remote="true" 
-      #   #        data-url="http://www.example.com/whatnot" 
-      #   #        data-method="delete" 
-      #   #        rel="nofollow">Remove Author</a>
-      #   #
-      #   link_to_remote("Remove Author", { :url    => { :action => "whatnot" }, 
-      #                                     :method => "delete"})
-      #
-      #
-      # You can override the generated HTML options by specifying a hash in
-      # <tt>options[:html]</tt>.
-      #
-      #   # Generates:
-      #   #     <a class="fine" 
-      #   #        href="#" 
-      #   #        data-remote="true" 
-      #   #        data-url="http://www.example.com/whatnot"
-      #   #        data-method="delete"
-      #   #        rel="nofollow">Remove Author</a>
-      #   #
-      #   link_to_remote("Remove Author", { :url    => { :action => "whatnot"  }, 
-      #                                     :method => "delete",
-      #                                     :html   => { :class  => "fine"    }})
-      #
-      #
-      # You can also specify a hash for <tt>options[:update]</tt> to allow for
-      # easy redirection of output to an other DOM element if a server-side
-      # error occurs:
-      #
-      # Example:
-      #   # Generates: 
-      #   #
-      #   #     <a href="#" 
-      #   #        data-url="http://www.example.com/destroy" 
-      #   #        data-update-success="posts" 
-      #   #        data-update-failure="error" 
-      #   #        data-remote="true">Delete this Post</a>'
-      #   #
-      #   link_to_remote "Delete this post",
-      #     :url => { :action => "destroy"},
-      #     :update => { :success => "posts", :failure => "error" }
-      #
-      # Optionally, you can use the <tt>options[:position]</tt> parameter to
-      # influence how the target DOM element is updated. It must be one of
-      # <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.
-      #
-      # Example:
-      #   # Generates:
-      #   #     <a href="#" 
-      #   #        data-remote="true" 
-      #   #        data-url="http://www.example.com/whatnot" 
-      #   #        data-update-position="bottom">Remove Author</a>
-      #   #
-      #   link_to_remote("Remove Author", :url => { :action => "whatnot" }, :position => :bottom)
-      #
-      #
-      # The method used is by default POST. You can also specify GET or you
-      # can simulate PUT or DELETE over POST. All specified with <tt>options[:method]</tt>
-      #
-      # Example:
-      #   # Generates: 
-      #   #     <a href='#'
-      #   #        data-url='/person/4' 
-      #   #        rel='nofollow' 
-      #   #        data-remote='true' 
-      #   #        data-method='delete'>Destroy</a>
-      #   #
-      #   link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
-      #
-      # By default, these remote requests are processed asynchronous during
-      # which various JavaScript callbacks can be triggered (for progress
-      # indicators and the likes). All callbacks get access to the
-      # <tt>request</tt> object, which holds the underlying XMLHttpRequest.
-      #
-      # To access the server response, use <tt>request.responseText</tt>, to
-      # find out the HTTP status, use <tt>request.status</tt>.
-      #
-      # Example:
-      #   # Generates: 
-      #   #
-      #   #     <a href='#' 
-      #   #        data-url='http://www.example.com/undo?n=5' 
-      #   #        data-oncomplete='undoRequestCompleted(request)' 
-      #   #        data-remote='true'>undo</a>
-      #   #
-      #   link_to_remote "undo",
-      #     :url => { :controller => "words", :action => "undo", :n => word_counter },
-      #     :complete => "undoRequestCompleted(request)"
-      #
-      # The callbacks that may be specified are (in order): 
-      #
-      # <tt>:loading</tt>::       Called when the remote document is being
-      #                           loaded with data by the browser.
-      # <tt>:loaded</tt>::        Called when the browser has finished loading
-      #                           the remote document.
-      # <tt>:interactive</tt>::   Called when the user can interact with the
-      #                           remote document, even though it has not
-      #                           finished loading.
-      # <tt>:success</tt>::       Called when the XMLHttpRequest is completed,
-      #                           and the HTTP status code is in the 2XX range.
-      # <tt>:failure</tt>::       Called when the XMLHttpRequest is completed,
-      #                           and the HTTP status code is not in the 2XX
-      #                           range.
-      # <tt>:complete</tt>::      Called when the XMLHttpRequest is complete
-      #                           (fires after success/failure if they are
-      #                           present).
-      #
-      # You can further refine <tt>:success</tt> and <tt>:failure</tt> by
-      # adding additional callbacks for specific status codes.
-      #
-      # Example:
-      #
-      #   # Generates:  
-      #   #     <a href='/testing/action'
-      #   #        date-remote='true'
-      #   #        data-failure="function(request){alert('HTTP Error '+ request.status +'+!');return false}"
-      #   #        data-404="function(request){alert('Not found...? Wrong URL...?')}"> Hello</a>
-      #   #
-      #   link_to_remote word,
-      #     :url => { :action => "action" },
-      #     404 => "alert('Not found...? Wrong URL...?')",
-      #     :failure => "alert('HTTP Error ' + request.status + '!')"
-      #
-      # A status code callback overrides the success/failure handlers if
-      # present.
-      #
-      # If you for some reason or another need synchronous processing (that'll
-      # block the browser while the request is happening), you can specify
-      # <tt>options[:type] = :synchronous</tt>.
-      #
-      # You can customize further browser side call logic by passing in
-      # JavaScript code snippets via some optional parameters. In their order
-      # of use these are:
-      #
-      # <tt>:confirm</tt>::      Adds confirmation dialog.
-      # <tt>:condition</tt>::    Perform remote request conditionally
-      #                          by this expression. Use this to
-      #                          describe browser-side conditions when
-      #                          request should not be initiated.
-      # <tt>:before</tt>::       Called before request is initiated.
-      # <tt>:after</tt>::        Called immediately after request was
-      #                          initiated and before <tt>:loading</tt>.
-      # <tt>:submit</tt>::       Specifies the DOM element ID that's used
-      #                          as the parent of the form elements. By
-      #                          default this is the current form, but
-      #                          it could just as well be the ID of a
-      #                          table row or any other DOM element.
-      # <tt>:with</tt>::         A JavaScript expression specifying
-      #                          the parameters for the XMLHttpRequest.
-      #                          Any expressions should return a valid
-      #                          URL query string.
-      #
-      #                          Example:
-      #
-      #                            :with => "'name=' + $('name').value"
-      #
-      # You can generate a link that uses the UJS drivers in the general case, while
-      # degrading gracefully to plain link behavior in the absence of
-      # JavaScript by setting <tt>html_options[:href]</tt> to an alternate URL.
-      # Note the extra curly braces around the <tt>options</tt> hash separate
-      # it as the second parameter from <tt>html_options</tt>, the third.
-      #
-      # Example:
-      #
-      #   # Generates:
-      #   #     <a href='/posts/1' 
-      #   #        rel='nofollow' 
-      #   #        data-remote='true' 
-      #   #        data-method='delete'> Delete this post</a>
-      #   #
-      #   link_to_remote "Delete this post",
-      #     { :update => "posts", :url => { :action => "destroy", :id => post.id } }
-      #     
-      def link_to_remote(name, options, html_options = {})
-        attributes = {}
-
-        attributes.merge!(:rel => "nofollow") if options[:method] && options[:method].to_s.downcase == "delete"
-        attributes.merge!(extract_remote_attributes!(options))
+      include UrlHelper
+      
+      def link_to_remote(name, url, options = {})
+        html = options.delete(:html) || {}
         
-        if confirm = options.delete(:confirm)
-          add_confirm_to_attributes!(attributes, confirm)
-        end
-
-        attributes.merge!(html_options)
-        href = html_options[:href].nil? ? "#" : html_options[:href]
-        attributes.merge!(:href => href)
-
-        content_tag(:a, name, attributes)
-      end
-  
-      # Returns an input of type button, which allows the unobtrusive JavaScript driver 
-      # to dynamically adjust its behaviour. The default driver behaviour is to call a
-      # remote action via XMLHttpRequest in the background.
-      # The options for specifying the target with :url and defining callbacks is the same
-      # as link_to_remote.
-      #
-      # Example:
-      #   
-      #   # Generates:
-      #   #     <input class="fine"
-      #   #            type="button" 
-      #   #            value="Remote outpost" 
-      #   #            data-remote="true" 
-      #   #            data-url="http://www.example.com/whatnot" />
-      #   #
-      #   button_to_remote("Remote outpost", { :url => { :action => "whatnot" }}, { :class => "fine"  })
-      #
-      def button_to_remote(name, options = {}, html_options = {})
-        attributes = html_options.merge!(:type => "button", :value => name)
-
-        if confirm = options.delete(:confirm)
-          add_confirm_to_attributes!(attributes, confirm)
-        end
-
-        if disable_with = options.delete(:disable_with)
-          add_disable_with_to_attributes!(attributes, disable_with)
-        end
-
-        attributes.merge!(extract_remote_attributes!(options))
-
-        tag(:input, attributes)
-      end
-
-      # Returns an input tag of type button, with the element name of +name+ and a value (i.e., display text) 
-      # of +value+  which will allow the unobtrusive JavaScript driver to dynamically adjust its behaviour 
-      # The default behaviour is to call a remote action via XMLHttpRequest in the background.
-      #
-      # request that reloads the page.
-      #
-      #  # Create a button that submits to the create action
-      #  #
-      #  # Generates: 
-      #  #      <input name='create_btn' 
-      #  #             type='button'
-      #  #             value='Create'
-      #  #             data-remote='true' 
-      #  #             data-url='/create' />
-      #  #
-      #  <%= submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %>
-      #
-      #  # Submit to the remote action update and update the DIV succeed or fail based
-      #  # on the success or failure of the request
-      #  #
-      #  # Generates: 
-      #  #    <input name='update_btn'
-      #  #           type='button'
-      #  #           value='Update'
-      #  #           date-remote-submit='true' 
-      #  #           data-url='/testing/update' 
-      #  #           data-success='succeed' 
-      #  #           data-failure='fail' />
-      #  #
-      #  <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' },
-      #     :update => { :success => "succeed", :failure => "fail" }
-      #
-      # <tt>options</tt> argument is the same as in form_remote_tag.
-      def submit_to_remote(name, value, options = {})
-        html_options = options.delete(:html) || {}
-        html_options.merge!(:name => name, :value => value, :type => "button")
-
-        attributes = extract_remote_attributes!(options)
-        attributes.merge!(html_options)
-        attributes["data-remote-submit"] = true
-        attributes.delete("data-remote")
-
-        tag(:input, attributes)
-      end
-
-      # Periodically provides the UJS driver with the information to call the specified 
-      # url (<tt>options[:url]</tt>) every <tt>options[:frequency]</tt> seconds (default is 10). Usually used to
-      # update a specified div (<tt>options[:update]</tt>) with the results
-      # of the remote call. The options for specifying the target with <tt>:url</tt>
-      # and defining callbacks is the same as link_to_remote.
-      # Examples:
-      #  # Call get_averages and put its results in 'avg' every 10 seconds
-      #  # Generates:
-      #  #      <script data-periodical='true' 
-      #  #              data-url='/get_averages' 
-      #  #              type='application/json' 
-      #  #              data-update-success='avg'
-      #  #              data-frequency='10'></script>
-      #  #
-      #  periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg')
-      #
-      #  # Call invoice every 10 seconds with the id of the customer
-      #  # If it succeeds, update the invoice DIV; if it fails, update the error DIV
-      #  # Generates:
-      #  #      <script data-periodical='true' 
-      #  #              data-url='/invoice/1' 
-      #  #              type='application/json' 
-      #  #              data-update-success='invoice' 
-      #  #              data-update-failure='error'
-      #  #              data-frequency='10'></script>"
-      #  #
-      #  periodically_call_remote(:url => { :action => 'invoice', :id => 1 },
-      #     :update => { :success => "invoice", :failure => "error" }
-      #
-      #  # Call update every 20 seconds and update the new_block DIV
-      #  # Generates:
-      #  #      <script data-periodical='true' 
-      #  #              data-url='update' 
-      #  #              type='application/json' 
-      #  #              data-update-success='news_block'
-      #  #              data-frequency='20'></script>
-      #  #
-      #  periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
-      #
-      def periodically_call_remote(options = {})
-        attributes = extract_observer_attributes!(options)
-        attributes["data-periodical"] = true 
-        attributes["data-frequency"] ||= 10
-
-        # periodically_call_remote does not need data-observe=true
-        attributes.delete('data-observe')
-
-        script_decorator(attributes).html_safe!
-      end
-
-      # Observes the field with the DOM ID specified by +field_id+ and calls a
-      # callback when its contents have changed. The default callback is an
-      # Ajax call. By default the value of the observed field is sent as a
-      # parameter with the Ajax call.
-      #
-      # Example:
-      #  # Generates: 
-      #  #      "<script type='text/javascript' 
-      #  #               data-observe='true' 
-      #  #               data-observed='suggest' 
-      #  #               data-frequency='0.25' 
-      #  #               type='application/json' 
-      #  #               data-url='/find_suggestion' 
-      #  #               data-update-success='suggest' 
-      #  #               data-with='q'></script>"
-      #  # 
-      #  <%= observe_field :suggest, :url => { :action => :find_suggestion },
-      #       :frequency => 0.25,
-      #       :update => :suggest,
-      #       :with => 'q'
-      #       %>
-      #
-      # Required +options+ are either of:
-      # <tt>:url</tt>::       +url_for+-style options for the action to call
-      #                       when the field has changed.
-      # <tt>:function</tt>::  Instead of making a remote call to a URL, you
-      #                       can specify javascript code to be called instead.
-      #                       Note that the value of this option is used as the
-      #                       *body* of the javascript function, a function definition
-      #                       with parameters named element and value will be generated for you
-      #                       for example:
-      #                         observe_field("glass", :frequency => 1, :function => "alert('Element changed')")
-      #                       will generate:
-      #                         new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')})
-      #                       The element parameter is the DOM element being observed, and the value is its value at the
-      #                       time the observer is triggered.
-      #
-      # Additional options are:
-      # <tt>:frequency</tt>:: The frequency (in seconds) at which changes to
-      #                       this field will be detected. Not setting this
-      #                       option at all or to a value equal to or less than
-      #                       zero will use event based observation instead of
-      #                       time based observation.
-      # <tt>:update</tt>::    Specifies the DOM ID of the element whose
-      #                       innerHTML should be updated with the
-      #                       XMLHttpRequest response text.
-      # <tt>:with</tt>::      A JavaScript expression specifying the parameters
-      #                       for the XMLHttpRequest. The default is to send the
-      #                       key and value of the observed field. Any custom
-      #                       expressions should return a valid URL query string.
-      #                       The value of the field is stored in the JavaScript
-      #                       variable +value+.
-      #
-      #                       Examples
-      #
-      #                         :with => "'my_custom_key=' + value"
-      #                         :with => "'person[name]=' + prompt('New name')"
-      #                         :with => "Form.Element.serialize('other-field')"
-      #
-      #                       Finally
-      #                         :with => 'name'
-      #                       is shorthand for
-      #                         :with => "'name=' + value"
-      #                       This essentially just changes the key of the parameter.
-      #
-      # Additionally, you may specify any of the options documented in the
-      # <em>Common options</em> section at the top of this document.
-      #
-      # Example:
-      #
-      #   # Sends params: {:title => 'Title of the book'} when the book_title input
-      #   # field is changed.
-      #   observe_field 'book_title',
-      #     :url => 'http://example.com/books/edit/1',
-      #     :with => 'title'
-      #
-      #
-      def observe_field(name, options = {})
-        html_options = options.delete(:callbacks)
-
-        options[:observed] = name
-        attributes = extract_observer_attributes!(options)
-        attributes.merge!(html_options) if html_options
-
-        script_decorator(attributes).html_safe!
-      end
-  
-      # Observes the form with the DOM ID specified by +form_id+ and calls a
-      # callback when its contents have changed. The default callback is an
-      # Ajax call. By default all fields of the observed field are sent as
-      # parameters with the Ajax call.
-      #
-      # The +options+ for +observe_form+ are the same as the options for
-      # +observe_field+. The JavaScript variable +value+ available to the
-      # <tt>:with</tt> option is set to the serialized form by default.
-      def observe_form(name, options = {})
-        html_options = options.delete(:callbacks)
-
-        options[:observed] = name
-        attributes = extract_observer_attributes!(options)
-        attributes.merge!(html_options) if html_options
-
-        script_decorator(attributes).html_safe!
-      end
-
-      def script_decorator(options)
-        attributes = %w(type="application/json")
-        attributes += options.map{|k, v| k + '="' + v.to_s + '"'}
-        "<script " + attributes.join(" ") + "></script>"
-      end
-
-      private
-
-        def extract_remote_attributes!(options)
-          attributes = options.delete(:html) || {}
-
-          attributes.merge!(extract_update_attributes!(options))
-          attributes.merge!(extract_request_attributes!(options))
-          attributes["data-remote"] = true 
-
-          if submit = options.delete(:submit)
-            attributes["data-submit"] = submit
-          end
-
-          attributes
-        end
-
-        def extract_request_attributes!(options)
-          attributes = {}
-          if method  = options.delete(:method)
-            attributes["data-method"] = method.to_s
-          end
-          
-          if type = options.delete(:type)
-            attributes["data-remote-type"] = type.to_s 
-          end
-
-          url_options = options.delete(:url)
-          url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
-          attributes["data-url"] = escape_javascript(url_for(url_options))  if url_options
-
-          purge_unused_attributes!(attributes)
+        update = options.delete(:update)
+        if update.is_a?(Hash)
+          html["data-update-success"] = update[:success]
+          html["data-update-failure"] = update[:failure]
+        else
+          html["data-update-success"] = update
         end
 
-        def extract_update_attributes!(options)
-          attributes = {}
-          update = options.delete(:update)
-          if update.is_a?(Hash)
-            attributes["data-update-success"] = update[:success]
-            attributes["data-update-failure"] = update[:failure]
-          else
-            attributes["data-update-success"] = update
-          end
-
-          if position = options.delete(:position)
-            attributes["data-update-position"] = position.to_s 
-          end
-
-          purge_unused_attributes!(attributes)
-        end
-
-        def extract_observer_attributes!(options)
-          callback = options.delete(:function)
-          frequency = options.delete(:frequency) || 10
-
-
-          attributes = extract_remote_attributes!(options)
-          attributes["data-observe"] = true
-          attributes["data-observed"] = options.delete(:observed)
-          attributes["data-onobserve"] = callback if callback
-          attributes["data-frequency"] = frequency if frequency && frequency.to_f != 0
-          attributes.delete("data-remote")
-
-          purge_unused_attributes!(attributes)
-        end
-
-        def purge_unused_attributes!(attributes)
-          attributes.delete_if {|key, value| value.nil? }
-          attributes
-        end
-    end
-
-    # TODO: All evaled goes here per wycat
-    module AjaxHelperCompat
-      include AjaxHelper
-
-      def link_to_remote(name, options, html_options = {})
-        set_callbacks(options, html_options)
-        set_with_and_condition_attributes(options, html_options)
-        super
+        html["data-update-position"] = options.delete(:position)
+        html["data-method"]          = options.delete(:method)
+        html["data-remote"]          = "true"
+        
+        html.merge!(options)
+        
+        url = url_for(url) if url.is_a?(Hash)
+        link_to(name, url, html)
       end
       
       def button_to_remote(name, options = {}, html_options = {})
-        set_callbacks(options, html_options)
-        set_with_and_condition_attributes(options, html_options)
-        super
-      end
-
-      def form_remote_tag(options, &block)
-        html = {}
-        set_callbacks(options, html)
-        set_with_and_condition_attributes(options, html)
-        options.merge!(:callbacks => html)
-        super
-      end
-
-      def observe_field(name, options = {})
-        html = {}
-        set_with_and_condition_attributes(options, html)
-        options.merge!(:callbacks => html)
-        super
+        url = options.delete(:url)
+        url = url_for(url) if url.is_a?(Hash)
+        
+        html_options.merge!(:type => "button", :value => name,
+          :"data-url" => url)
+        
+        tag(:input, html_options)
       end
       
-      def observe_form(name, options = {})
-        html = {}
-        set_with_and_condition_attributes(options, html)
-        options.merge!(:callbacks => html)
-        super
-      end
-
-      private
+      module Rails2Compatibility
         def set_callbacks(options, html)
-          [:before, :after, :uninitialized, :complete, :failure, :success, :interactive, :loaded, :loading].each do |type|
-            html["data-on#{type}"]  = options.delete(type.to_sym)
+          [:complete, :failure, :success, :interactive, :loaded, :loading].each do |type|
+            html["data-#{type}-code"]  = options.delete(type.to_sym)
           end
 
           options.each do |option, value|
             if option.is_a?(Integer)
-              html["data-on#{option}"] = options.delete(option)
+              html["data-#{option}-code"] = options.delete(option)
             end
           end
         end
-
-        def set_with_and_condition_attributes(options, html)
-          if with = options.delete(:with)
-            html["data-with"] = with
-          end
-
-          if condition = options.delete(:condition)
-            html["data-condition"] = condition
+        
+        def link_to_remote(name, url, options = nil)
+          if !options && url.is_a?(Hash) && url.key?(:url)
+            url, options = url.delete(:url), url
           end
+          
+          set_callbacks(options, options[:html] ||= {})
+          
+          super
+        end
+        
+        def button_to_remote(name, options = {}, html_options = {})
+          set_callbacks(options, html_options)
+          super
         end
+      end
+      
     end
   end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 1615f135b4..20e9916d62 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -262,8 +262,23 @@ module ActionView
       # FormTagHelper#form_tag.
       def form_for(record_or_name_or_array, *args, &proc)
         raise ArgumentError, "Missing block" unless block_given?
+
         options = args.extract_options!
-        object_name = extract_object_name_for_form!(args, options, record_or_name_or_array)
+
+        case record_or_name_or_array
+        when String, Symbol
+          object_name = record_or_name_or_array
+        when Array
+          object = record_or_name_or_array.last
+          object_name = ActionController::RecordIdentifier.singular_class_name(object)
+          apply_form_for_options!(record_or_name_or_array, options)
+          args.unshift object
+        else
+          object = record_or_name_or_array
+          object_name = ActionController::RecordIdentifier.singular_class_name(object)
+          apply_form_for_options!([object], options)
+          args.unshift object
+        end
 
         concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
         fields_for(object_name, *(args << options), &proc)
@@ -727,25 +742,6 @@ module ActionView
       def radio_button(object_name, method, tag_value, options = {})
         InstanceTag.new(object_name, method, self, options.delete(:object)).to_radio_button_tag(tag_value, options)
       end
-
-      private
-        def extract_object_name_for_form!(args, options, record_or_name_or_array)
-          case record_or_name_or_array
-          when String, Symbol
-            object_name = record_or_name_or_array
-          when Array
-            object = record_or_name_or_array.last
-            object_name = ActionController::RecordIdentifier.singular_class_name(object)
-            apply_form_for_options!(record_or_name_or_array, options)
-            args.unshift object
-          else
-            object = record_or_name_or_array
-            object_name = ActionController::RecordIdentifier.singular_class_name(object)
-            apply_form_for_options!([object], options)
-            args.unshift object
-          end
-          object_name
-        end
     end
 
     module InstanceTagMethods #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index ebce5c1513..048bedc7ba 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -352,24 +352,33 @@ module ActionView
       #   # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
       #
       #   submit_tag "Complete sale", :disable_with => "Please wait..."
-      #   # => <input name="commit" data-disable-with="Please wait..."
+      #   # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();"
       #   #    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" data-disable-with="Editing..."
+      #   # => <input class="edit-button" onclick="this.disabled=true;this.value='Editing...';this.form.submit();"
       #   #    name="commit" type="submit" value="Edit" />
       def submit_tag(value = "Save changes", options = {})
         options.stringify_keys!
 
         if disable_with = options.delete("disable_with")
-          add_disable_with_to_attributes!(options, disable_with)
+          disable_with = "this.value='#{disable_with}'"
+          disable_with << ";#{options.delete('onclick')}" if options['onclick']
+          
+          options["onclick"]  = "if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }"
+          options["onclick"] << "else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';"
+          options["onclick"] << "hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }"
+          options["onclick"] << "this.setAttribute('originalValue', this.value);this.disabled = true;#{disable_with};"
+          options["onclick"] << "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());"
+          options["onclick"] << "if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;"
         end
 
         if confirm = options.delete("confirm")
-          add_confirm_to_attributes!(options, confirm)
+          options["onclick"] ||= 'return true;'
+          options["onclick"] = "if (!#{confirm_javascript_function(confirm)}) return false; #{options['onclick']}"
         end
 
         tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys)
@@ -402,7 +411,8 @@ module ActionView
         options.stringify_keys!
 
         if confirm = options.delete("confirm")
-          add_confirm_to_attributes!(options, confirm)
+          options["onclick"] ||= ''
+          options["onclick"] += "return #{confirm_javascript_function(confirm)};"
         end
 
         tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options.stringify_keys)
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index 02d0a88189..06a9d3405a 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -39,7 +39,7 @@ module ActionView
         JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts')
       end
 
-      include AjaxHelperCompat
+      include PrototypeHelper
 
       # Returns a link of the given +name+ that will trigger a JavaScript +function+ using the
       # onclick handler and return false after the fact.
@@ -187,57 +187,22 @@ module ActionView
         "\n//#{cdata_section("\n#{content}\n//")}\n"
       end
 
-    protected
-      def convert_options_to_javascript!(html_options, url = '')
-        confirm = html_options.delete("confirm")
-
-        if html_options.key?("popup")
-          ActiveSupport::Deprecation.warn(":popup has been deprecated", caller)
-        end
-
-        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, url)
-        elsif confirm
-          add_confirm_to_attributes!(html_options, confirm)
-        elsif method
-          add_method_to_attributes!(html_options, method, url)
-        end
-      end
-
-      def add_confirm_to_attributes!(html_options, confirm)
-          html_options["data-confirm"] = confirm if confirm
-      end
-
-      def add_method_to_attributes!(html_options, method, url = nil)
-        html_options["rel"] = "nofollow" if method.to_s.downcase == "delete"
-        html_options["data-method"] = method
-        if url.size > 0
-          html_options["data-url"] = url
-        end
-      end
-
-      def add_disable_with_to_attributes!(html_options, disable_with)
-          html_options["data-disable-with"] = disable_with if disable_with
-      end
-
-      def options_for_javascript(options)
-        if options.empty?
-          '{}'
-        else
-          "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
+      protected
+        def options_for_javascript(options)
+          if options.empty?
+            '{}'
+          else
+            "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
+          end
         end
-      end
 
-      def array_or_string_for_javascript(option)
-        if option.kind_of?(Array)
-          "['#{option.join('\',\'')}']"
-        elsif !option.nil?
-          "'#{option}'"
+        def array_or_string_for_javascript(option)
+          if option.kind_of?(Array)
+            "['#{option.join('\',\'')}']"
+          elsif !option.nil?
+            "'#{option}'"
+          end
         end
-      end
     end
   end
 end
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index d861810f19..bef93dd0f8 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -1,7 +1,6 @@
 require 'set'
 require 'active_support/json'
 require 'active_support/core_ext/object/returning'
-require 'action_view/helpers/scriptaculous_helper'
 
 module ActionView
   module Helpers
@@ -28,6 +27,40 @@ module ActionView
     # ActionView::Helpers::JavaScriptHelper for more information on including
     # this and other JavaScript files in your Rails templates.)
     #
+    # Now you're ready to call a remote action either through a link...
+    #
+    #  link_to_remote "Add to cart",
+    #    :url => { :action => "add", :id => product.id },
+    #    :update => { :success => "cart", :failure => "error" }
+    #
+    # ...through a form...
+    #
+    #  <% form_remote_tag :url => '/shipping' do -%>
+    #    <div><%= submit_tag 'Recalculate Shipping' %></div>
+    #  <% end -%>
+    #
+    # ...periodically...
+    #
+    #  periodically_call_remote(:url => 'update', :frequency => '5', :update => 'ticker')
+    #
+    # ...or through an observer (i.e., a form or field that is observed and calls a remote
+    # action when changed).
+    #
+    #  <%= observe_field(:searchbox,
+    #       :url => { :action => :live_search }),
+    #       :frequency => 0.5,
+    #       :update => :hits,
+    #       :with => 'query'
+    #       %>
+    #
+    # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than
+    # are listed here); check out the documentation for each method to find out more about its usage and options.
+    #
+    # === Common Options
+    # See link_to_remote for documentation of options common to all Ajax
+    # helpers; any of the options specified by link_to_remote can be used
+    # by the other helpers.
+    #
     # == Designing your Rails actions for Ajax
     # When building your action handlers (that is, the Rails actions that receive your background requests), it's
     # important to remember a few things.  First, whatever your action would normally return to the browser, it will
@@ -74,8 +107,6 @@ module ActionView
     # See JavaScriptGenerator for information on updating multiple elements
     # on the page in an Ajax response.
     module PrototypeHelper
-      include ScriptaculousHelper
-
       unless const_defined? :CALLBACKS
         CALLBACKS    = Set.new([ :create, :uninitialized, :loading, :loaded,
                          :interactive, :complete, :failure, :success ] +
@@ -85,6 +116,325 @@ module ActionView
                          :form, :with, :update, :script, :type ]).merge(CALLBACKS)
       end
 
+      # Returns a link to a remote action defined by <tt>options[:url]</tt>
+      # (using the url_for format) that's called in the background using
+      # XMLHttpRequest. The result of that request can then be inserted into a
+      # DOM object whose id can be specified with <tt>options[:update]</tt>.
+      # Usually, the result would be a partial prepared by the controller with
+      # render :partial.
+      #
+      # Examples:
+      #   # Generates: <a href="#" onclick="new Ajax.Updater('posts', '/blog/destroy/3', {asynchronous:true, evalScripts:true});
+      #   #            return false;">Delete this post</a>
+      #   link_to_remote "Delete this post", :update => "posts",
+      #     :url => { :action => "destroy", :id => post.id }
+      #
+      #   # Generates: <a href="#" onclick="new Ajax.Updater('emails', '/mail/list_emails', {asynchronous:true, evalScripts:true});
+      #   #            return false;"><img alt="Refresh" src="/images/refresh.png?" /></a>
+      #   link_to_remote(image_tag("refresh"), :update => "emails",
+      #     :url => { :action => "list_emails" })
+      #
+      # You can override the generated HTML options by specifying a hash in
+      # <tt>options[:html]</tt>.
+      #
+      #   link_to_remote "Delete this post", :update => "posts",
+      #     :url  => post_url(@post), :method => :delete,
+      #     :html => { :class  => "destructive" }
+      #
+      # You can also specify a hash for <tt>options[:update]</tt> to allow for
+      # easy redirection of output to an other DOM element if a server-side
+      # error occurs:
+      #
+      # Example:
+      #   # Generates: <a href="#" onclick="new Ajax.Updater({success:'posts',failure:'error'}, '/blog/destroy/5',
+      #   #            {asynchronous:true, evalScripts:true}); return false;">Delete this post</a>
+      #   link_to_remote "Delete this post",
+      #     :url => { :action => "destroy", :id => post.id },
+      #     :update => { :success => "posts", :failure => "error" }
+      #
+      # Optionally, you can use the <tt>options[:position]</tt> parameter to
+      # influence how the target DOM element is updated. It must be one of
+      # <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.
+      #
+      # The method used is by default POST. You can also specify GET or you
+      # can simulate PUT or DELETE over POST. All specified with <tt>options[:method]</tt>
+      #
+      # Example:
+      #   # Generates: <a href="#" onclick="new Ajax.Request('/person/4', {asynchronous:true, evalScripts:true, method:'delete'});
+      #   #            return false;">Destroy</a>
+      #   link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
+      #
+      # By default, these remote requests are processed asynchronous during
+      # which various JavaScript callbacks can be triggered (for progress
+      # indicators and the likes). All callbacks get access to the
+      # <tt>request</tt> object, which holds the underlying XMLHttpRequest.
+      #
+      # To access the server response, use <tt>request.responseText</tt>, to
+      # find out the HTTP status, use <tt>request.status</tt>.
+      #
+      # Example:
+      #   # Generates: <a href="#" onclick="new Ajax.Request('/words/undo?n=33', {asynchronous:true, evalScripts:true,
+      #   #            onComplete:function(request){undoRequestCompleted(request)}}); return false;">hello</a>
+      #   word = 'hello'
+      #   link_to_remote word,
+      #     :url => { :action => "undo", :n => word_counter },
+      #     :complete => "undoRequestCompleted(request)"
+      #
+      # The callbacks that may be specified are (in order):
+      #
+      # <tt>:loading</tt>::       Called when the remote document is being
+      #                           loaded with data by the browser.
+      # <tt>:loaded</tt>::        Called when the browser has finished loading
+      #                           the remote document.
+      # <tt>:interactive</tt>::   Called when the user can interact with the
+      #                           remote document, even though it has not
+      #                           finished loading.
+      # <tt>:success</tt>::       Called when the XMLHttpRequest is completed,
+      #                           and the HTTP status code is in the 2XX range.
+      # <tt>:failure</tt>::       Called when the XMLHttpRequest is completed,
+      #                           and the HTTP status code is not in the 2XX
+      #                           range.
+      # <tt>:complete</tt>::      Called when the XMLHttpRequest is complete
+      #                           (fires after success/failure if they are
+      #                           present).
+      #
+      # You can further refine <tt>:success</tt> and <tt>:failure</tt> by
+      # adding additional callbacks for specific status codes.
+      #
+      # Example:
+      #   # Generates: <a href="#" onclick="new Ajax.Request('/testing/action', {asynchronous:true, evalScripts:true,
+      #   #            on404:function(request){alert('Not found...? Wrong URL...?')},
+      #   #            onFailure:function(request){alert('HTTP Error ' + request.status + '!')}}); return false;">hello</a>
+      #   link_to_remote word,
+      #     :url => { :action => "action" },
+      #     404 => "alert('Not found...? Wrong URL...?')",
+      #     :failure => "alert('HTTP Error ' + request.status + '!')"
+      #
+      # A status code callback overrides the success/failure handlers if
+      # present.
+      #
+      # If you for some reason or another need synchronous processing (that'll
+      # block the browser while the request is happening), you can specify
+      # <tt>options[:type] = :synchronous</tt>.
+      #
+      # You can customize further browser side call logic by passing in
+      # JavaScript code snippets via some optional parameters. In their order
+      # of use these are:
+      #
+      # <tt>:confirm</tt>::      Adds confirmation dialog.
+      # <tt>:condition</tt>::    Perform remote request conditionally
+      #                          by this expression. Use this to
+      #                          describe browser-side conditions when
+      #                          request should not be initiated.
+      # <tt>:before</tt>::       Called before request is initiated.
+      # <tt>:after</tt>::        Called immediately after request was
+      #                          initiated and before <tt>:loading</tt>.
+      # <tt>:submit</tt>::       Specifies the DOM element ID that's used
+      #                          as the parent of the form elements. By
+      #                          default this is the current form, but
+      #                          it could just as well be the ID of a
+      #                          table row or any other DOM element.
+      # <tt>:with</tt>::         A JavaScript expression specifying
+      #                          the parameters for the XMLHttpRequest.
+      #                          Any expressions should return a valid
+      #                          URL query string.
+      #
+      #                          Example:
+      #
+      #                            :with => "'name=' + $('name').value"
+      #
+      # You can generate a link that uses AJAX in the general case, while
+      # degrading gracefully to plain link behavior in the absence of
+      # JavaScript by setting <tt>html_options[:href]</tt> to an alternate URL.
+      # Note the extra curly braces around the <tt>options</tt> hash separate
+      # it as the second parameter from <tt>html_options</tt>, the third.
+      #
+      # Example:
+      #   link_to_remote "Delete this post",
+      #     { :update => "posts", :url => { :action => "destroy", :id => post.id } },
+      #     :href => url_for(:action => "destroy", :id => post.id)
+      def link_to_remote(name, options = {}, html_options = nil)
+        link_to_function(name, remote_function(options), html_options || options.delete(:html))
+      end
+
+      # Creates a button with an onclick event which calls a remote action
+      # via XMLHttpRequest
+      # The options for specifying the target with :url
+      # and defining callbacks is the same as link_to_remote.
+      def button_to_remote(name, options = {}, html_options = {})
+        button_to_function(name, remote_function(options), html_options)
+      end
+
+      # Periodically calls the specified url (<tt>options[:url]</tt>) every
+      # <tt>options[:frequency]</tt> seconds (default is 10). Usually used to
+      # update a specified div (<tt>options[:update]</tt>) with the results
+      # of the remote call. The options for specifying the target with <tt>:url</tt>
+      # and defining callbacks is the same as link_to_remote.
+      # Examples:
+      #  # Call get_averages and put its results in 'avg' every 10 seconds
+      #  # Generates:
+      #  #      new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages',
+      #  #      {asynchronous:true, evalScripts:true})}, 10)
+      #  periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg')
+      #
+      #  # Call invoice every 10 seconds with the id of the customer
+      #  # If it succeeds, update the invoice DIV; if it fails, update the error DIV
+      #  # Generates:
+      #  #      new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'},
+      #  #      '/testing/invoice/16', {asynchronous:true, evalScripts:true})}, 10)
+      #  periodically_call_remote(:url => { :action => 'invoice', :id => customer.id },
+      #     :update => { :success => "invoice", :failure => "error" }
+      #
+      #  # Call update every 20 seconds and update the new_block DIV
+      #  # Generates:
+      #  # new PeriodicalExecuter(function() {new Ajax.Updater('news_block', 'update', {asynchronous:true, evalScripts:true})}, 20)
+      #  periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
+      #
+      def periodically_call_remote(options = {})
+         frequency = options[:frequency] || 10 # every ten seconds by default
+         code = "new PeriodicalExecuter(function() {#{remote_function(options)}}, #{frequency})"
+         javascript_tag(code)
+      end
+
+      # Returns a form tag that will submit using XMLHttpRequest in the
+      # background instead of the regular reloading POST arrangement. 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>). The options for
+      # specifying the target with <tt>:url</tt> and defining callbacks is the same as
+      # +link_to_remote+.
+      #
+      # A "fall-through" target for browsers that doesn't do JavaScript can be
+      # specified with the <tt>:action</tt>/<tt>:method</tt> options on <tt>:html</tt>.
+      #
+      # Example:
+      #   # Generates:
+      #   #      <form action="/some/place" method="post" onsubmit="new Ajax.Request('',
+      #   #      {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
+      #   form_remote_tag :html => { :action =>
+      #     url_for(:controller => "some", :action => "place") }
+      #
+      # The Hash passed to the <tt>:html</tt> key is equivalent to the options (2nd)
+      # argument in the FormTagHelper.form_tag method.
+      #
+      # By default the fall-through action is the same as the one specified in
+      # the <tt>:url</tt> (and the default method is <tt>:post</tt>).
+      #
+      # form_remote_tag also takes a block, like form_tag:
+      #   # Generates:
+      #   #     <form action="/" method="post" onsubmit="new Ajax.Request('/',
+      #   #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});
+      #   #     return false;"> <div><input name="commit" type="submit" value="Save" /></div>
+      #   #     </form>
+      #   <% form_remote_tag :url => '/posts' do -%>
+      #     <div><%= submit_tag 'Save' %></div>
+      #   <% end -%>
+      def form_remote_tag(options = {}, &block)
+        options[:form] = true
+
+        options[:html] ||= {}
+        options[:html][:onsubmit] =
+          (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
+          "#{remote_function(options)}; return false;"
+
+        form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
+      end
+
+      # Creates a form that will submit using XMLHttpRequest in the background
+      # instead of the regular reloading POST arrangement and a scope around a
+      # specific resource that is used as a base for questioning about
+      # values for the fields.
+      #
+      # === Resource
+      #
+      # Example:
+      #   <% remote_form_for(@post) do |f| %>
+      #     ...
+      #   <% end %>
+      #
+      # This will expand to be the same as:
+      #
+      #   <% remote_form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
+      #     ...
+      #   <% end %>
+      #
+      # === Nested Resource
+      #
+      # Example:
+      #   <% remote_form_for([@post, @comment]) do |f| %>
+      #     ...
+      #   <% end %>
+      #
+      # This will expand to be the same as:
+      #
+      #   <% remote_form_for :comment, @comment, :url => post_comment_path(@post, @comment), :html => { :method => :put, :class => "edit_comment", :id => "edit_comment_45" } do |f| %>
+      #     ...
+      #   <% end %>
+      #
+      # If you don't need to attach a form to a resource, then check out form_remote_tag.
+      #
+      # See FormHelper#form_for for additional semantics.
+      def remote_form_for(record_or_name_or_array, *args, &proc)
+        options = args.extract_options!
+
+        case record_or_name_or_array
+        when String, Symbol
+          object_name = record_or_name_or_array
+        when Array
+          object = record_or_name_or_array.last
+          object_name = ActionController::RecordIdentifier.singular_class_name(object)
+          apply_form_for_options!(record_or_name_or_array, options)
+          args.unshift object
+        else
+          object      = record_or_name_or_array
+          object_name = ActionController::RecordIdentifier.singular_class_name(record_or_name_or_array)
+          apply_form_for_options!(object, options)
+          args.unshift object
+        end
+
+        concat(form_remote_tag(options))
+        fields_for(object_name, *(args << options), &proc)
+        concat('</form>'.html_safe!)
+      end
+      alias_method :form_remote_for, :remote_form_for
+
+      # Returns a button input tag with the element name of +name+ and a value (i.e., display text) of +value+
+      # that will submit form using XMLHttpRequest in the background instead of a regular POST request that
+      # reloads the page.
+      #
+      #  # Create a button that submits to the create action
+      #  #
+      #  # Generates: <input name="create_btn" onclick="new Ajax.Request('/testing/create',
+      #  #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
+      #  #     return false;" type="button" value="Create" />
+      #  <%= submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %>
+      #
+      #  # Submit to the remote action update and update the DIV succeed or fail based
+      #  # on the success or failure of the request
+      #  #
+      #  # Generates: <input name="update_btn" onclick="new Ajax.Updater({success:'succeed',failure:'fail'},
+      #  #      '/testing/update', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
+      #  #      return false;" type="button" value="Update" />
+      #  <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' },
+      #     :update => { :success => "succeed", :failure => "fail" }
+      #
+      # <tt>options</tt> argument is the same as in form_remote_tag.
+      def submit_to_remote(name, value, options = {})
+        options[:with] ||= 'Form.serialize(this.form)'
+
+        html_options = options.delete(:html) || {}
+        html_options[:name] = name
+
+        button_to_remote(value, options, html_options)
+      end
+
+      # Returns '<tt>eval(request.responseText)</tt>' which is the JavaScript function
+      # that +form_remote_tag+ can call in <tt>:complete</tt> to evaluate a multiple
+      # update return document using +update_element_function+ calls.
+      def evaluate_remote_response
+        "eval(request.responseText)"
+      end
+
       # Returns the JavaScript needed for a remote function.
       # Takes the same arguments as link_to_remote.
       #
@@ -126,6 +476,99 @@ module ActionView
         return function
       end
 
+      # Observes the field with the DOM ID specified by +field_id+ and calls a
+      # callback when its contents have changed. The default callback is an
+      # Ajax call. By default the value of the observed field is sent as a
+      # parameter with the Ajax call.
+      #
+      # Example:
+      #  # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest',
+      #  #         '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})})
+      #  <%= observe_field :suggest, :url => { :action => :find_suggestion },
+      #       :frequency => 0.25,
+      #       :update => :suggest,
+      #       :with => 'q'
+      #       %>
+      #
+      # Required +options+ are either of:
+      # <tt>:url</tt>::       +url_for+-style options for the action to call
+      #                       when the field has changed.
+      # <tt>:function</tt>::  Instead of making a remote call to a URL, you
+      #                       can specify javascript code to be called instead.
+      #                       Note that the value of this option is used as the
+      #                       *body* of the javascript function, a function definition
+      #                       with parameters named element and value will be generated for you
+      #                       for example:
+      #                         observe_field("glass", :frequency => 1, :function => "alert('Element changed')")
+      #                       will generate:
+      #                         new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')})
+      #                       The element parameter is the DOM element being observed, and the value is its value at the
+      #                       time the observer is triggered.
+      #
+      # Additional options are:
+      # <tt>:frequency</tt>:: The frequency (in seconds) at which changes to
+      #                       this field will be detected. Not setting this
+      #                       option at all or to a value equal to or less than
+      #                       zero will use event based observation instead of
+      #                       time based observation.
+      # <tt>:update</tt>::    Specifies the DOM ID of the element whose
+      #                       innerHTML should be updated with the
+      #                       XMLHttpRequest response text.
+      # <tt>:with</tt>::      A JavaScript expression specifying the parameters
+      #                       for the XMLHttpRequest. The default is to send the
+      #                       key and value of the observed field. Any custom
+      #                       expressions should return a valid URL query string.
+      #                       The value of the field is stored in the JavaScript
+      #                       variable +value+.
+      #
+      #                       Examples
+      #
+      #                         :with => "'my_custom_key=' + value"
+      #                         :with => "'person[name]=' + prompt('New name')"
+      #                         :with => "Form.Element.serialize('other-field')"
+      #
+      #                       Finally
+      #                         :with => 'name'
+      #                       is shorthand for
+      #                         :with => "'name=' + value"
+      #                       This essentially just changes the key of the parameter.
+      #
+      # Additionally, you may specify any of the options documented in the
+      # <em>Common options</em> section at the top of this document.
+      #
+      # Example:
+      #
+      #   # Sends params: {:title => 'Title of the book'} when the book_title input
+      #   # field is changed.
+      #   observe_field 'book_title',
+      #     :url => 'http://example.com/books/edit/1',
+      #     :with => 'title'
+      #
+      #
+      def observe_field(field_id, options = {})
+        if options[:frequency] && options[:frequency] > 0
+          build_observer('Form.Element.Observer', field_id, options)
+        else
+          build_observer('Form.Element.EventObserver', field_id, options)
+        end
+      end
+
+      # Observes the form with the DOM ID specified by +form_id+ and calls a
+      # callback when its contents have changed. The default callback is an
+      # Ajax call. By default all fields of the observed field are sent as
+      # parameters with the Ajax call.
+      #
+      # The +options+ for +observe_form+ are the same as the options for
+      # +observe_field+. The JavaScript variable +value+ available to the
+      # <tt>:with</tt> option is set to the serialized form by default.
+      def observe_form(form_id, options = {})
+        if options[:frequency]
+          build_observer('Form.Observer', form_id, options)
+        else
+          build_observer('Form.EventObserver', form_id, options)
+        end
+      end
+
       # All the methods were moved to GeneratorMethods so that
       # #include_helpers_from_context has nothing to overwrite.
       class JavaScriptGenerator #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 837dca6149..d6bfc6d4c9 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -291,6 +291,9 @@ module ActionView
           request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
         end
 
+        if confirm = html_options.delete("confirm")
+          html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
+        end
 
         url = options.is_a?(String) ? options : self.url_for(options)
         name ||= url
@@ -548,6 +551,48 @@ module ActionView
       end
 
       private
+        def convert_options_to_javascript!(html_options, url = '')
+          confirm = html_options.delete("confirm")
+          method, href = html_options.delete("method"), html_options['href']
+
+          if html_options.key?("popup")
+            ActiveSupport::Deprecation.warn(":popup has been deprecated", caller)
+          end
+
+          html_options["onclick"] = case
+            when confirm && method
+              "if (#{confirm_javascript_function(confirm)}) { #{method_javascript_function(method, url, href)} };return false;"
+            when confirm
+              "return #{confirm_javascript_function(confirm)};"
+            when method
+              "#{method_javascript_function(method, url, href)}return false;"
+            else
+              html_options["onclick"]
+          end
+        end
+
+        def confirm_javascript_function(confirm)
+          "confirm('#{escape_javascript(confirm)}')"
+        end
+
+        def method_javascript_function(method, url = '', href = nil)
+          action = (href && url.size > 0) ? "'#{url}'" : 'this.href'
+          submit_function =
+            "var f = document.createElement('form'); f.style.display = 'none'; " +
+            "this.parentNode.appendChild(f); f.method = 'POST'; f.action = #{action};"
+
+          unless method == :post
+            submit_function << "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "
+            submit_function << "m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); f.appendChild(m);"
+          end
+
+          if protect_against_forgery?
+            submit_function << "var s = document.createElement('input'); s.setAttribute('type', 'hidden'); "
+            submit_function << "s.setAttribute('name', '#{request_forgery_protection_token}'); s.setAttribute('value', '#{escape_javascript form_authenticity_token}'); f.appendChild(s);"
+          end
+          submit_function << "f.submit();"
+        end
+
         # Processes the +html_options+ hash, converting the boolean
         # attributes from true/false form into the form required by
         # HTML/XHTML.  (An attribute is considered to be boolean if
-- 
cgit v1.2.3


From 61c9b1648703c29133c3ea2ec083e275d95edbec Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 14:53:43 -0600
Subject: Move observe_field and observe_form to prototype_legacy_helper plugin

---
 .../lib/action_view/helpers/prototype_helper.rb    | 189 ++++-----------------
 1 file changed, 35 insertions(+), 154 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index bef93dd0f8..92f4ca838f 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -43,16 +43,6 @@ module ActionView
     #
     #  periodically_call_remote(:url => 'update', :frequency => '5', :update => 'ticker')
     #
-    # ...or through an observer (i.e., a form or field that is observed and calls a remote
-    # action when changed).
-    #
-    #  <%= observe_field(:searchbox,
-    #       :url => { :action => :live_search }),
-    #       :frequency => 0.5,
-    #       :update => :hits,
-    #       :with => 'query'
-    #       %>
-    #
     # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than
     # are listed here); check out the documentation for each method to find out more about its usage and options.
     #
@@ -476,99 +466,6 @@ module ActionView
         return function
       end
 
-      # Observes the field with the DOM ID specified by +field_id+ and calls a
-      # callback when its contents have changed. The default callback is an
-      # Ajax call. By default the value of the observed field is sent as a
-      # parameter with the Ajax call.
-      #
-      # Example:
-      #  # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest',
-      #  #         '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})})
-      #  <%= observe_field :suggest, :url => { :action => :find_suggestion },
-      #       :frequency => 0.25,
-      #       :update => :suggest,
-      #       :with => 'q'
-      #       %>
-      #
-      # Required +options+ are either of:
-      # <tt>:url</tt>::       +url_for+-style options for the action to call
-      #                       when the field has changed.
-      # <tt>:function</tt>::  Instead of making a remote call to a URL, you
-      #                       can specify javascript code to be called instead.
-      #                       Note that the value of this option is used as the
-      #                       *body* of the javascript function, a function definition
-      #                       with parameters named element and value will be generated for you
-      #                       for example:
-      #                         observe_field("glass", :frequency => 1, :function => "alert('Element changed')")
-      #                       will generate:
-      #                         new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')})
-      #                       The element parameter is the DOM element being observed, and the value is its value at the
-      #                       time the observer is triggered.
-      #
-      # Additional options are:
-      # <tt>:frequency</tt>:: The frequency (in seconds) at which changes to
-      #                       this field will be detected. Not setting this
-      #                       option at all or to a value equal to or less than
-      #                       zero will use event based observation instead of
-      #                       time based observation.
-      # <tt>:update</tt>::    Specifies the DOM ID of the element whose
-      #                       innerHTML should be updated with the
-      #                       XMLHttpRequest response text.
-      # <tt>:with</tt>::      A JavaScript expression specifying the parameters
-      #                       for the XMLHttpRequest. The default is to send the
-      #                       key and value of the observed field. Any custom
-      #                       expressions should return a valid URL query string.
-      #                       The value of the field is stored in the JavaScript
-      #                       variable +value+.
-      #
-      #                       Examples
-      #
-      #                         :with => "'my_custom_key=' + value"
-      #                         :with => "'person[name]=' + prompt('New name')"
-      #                         :with => "Form.Element.serialize('other-field')"
-      #
-      #                       Finally
-      #                         :with => 'name'
-      #                       is shorthand for
-      #                         :with => "'name=' + value"
-      #                       This essentially just changes the key of the parameter.
-      #
-      # Additionally, you may specify any of the options documented in the
-      # <em>Common options</em> section at the top of this document.
-      #
-      # Example:
-      #
-      #   # Sends params: {:title => 'Title of the book'} when the book_title input
-      #   # field is changed.
-      #   observe_field 'book_title',
-      #     :url => 'http://example.com/books/edit/1',
-      #     :with => 'title'
-      #
-      #
-      def observe_field(field_id, options = {})
-        if options[:frequency] && options[:frequency] > 0
-          build_observer('Form.Element.Observer', field_id, options)
-        else
-          build_observer('Form.Element.EventObserver', field_id, options)
-        end
-      end
-
-      # Observes the form with the DOM ID specified by +form_id+ and calls a
-      # callback when its contents have changed. The default callback is an
-      # Ajax call. By default all fields of the observed field are sent as
-      # parameters with the Ajax call.
-      #
-      # The +options+ for +observe_form+ are the same as the options for
-      # +observe_field+. The JavaScript variable +value+ available to the
-      # <tt>:with</tt> option is set to the serialized form by default.
-      def observe_form(form_id, options = {})
-        if options[:frequency]
-          build_observer('Form.Observer', form_id, options)
-        else
-          build_observer('Form.EventObserver', form_id, options)
-        end
-      end
-
       # All the methods were moved to GeneratorMethods so that
       # #include_helpers_from_context has nothing to overwrite.
       class JavaScriptGenerator #:nodoc:
@@ -1042,65 +939,49 @@ module ActionView
         javascript_tag update_page(&block), html_options
       end
 
-    protected
-      def options_for_ajax(options)
-        js_options = build_callbacks(options)
-
-        js_options['asynchronous'] = options[:type] != :synchronous
-        js_options['method']       = method_option_to_s(options[:method]) if options[:method]
-        js_options['insertion']    = "'#{options[:position].to_s.downcase}'" if options[:position]
-        js_options['evalScripts']  = options[:script].nil? || options[:script]
-
-        if options[:form]
-          js_options['parameters'] = 'Form.serialize(this)'
-        elsif options[:submit]
-          js_options['parameters'] = "Form.serialize('#{options[:submit]}')"
-        elsif options[:with]
-          js_options['parameters'] = options[:with]
-        end
-
-        if protect_against_forgery? && !options[:form]
-          if js_options['parameters']
-            js_options['parameters'] << " + '&"
-          else
-            js_options['parameters'] = "'"
+      protected
+        def options_for_ajax(options)
+          js_options = build_callbacks(options)
+
+          js_options['asynchronous'] = options[:type] != :synchronous
+          js_options['method']       = method_option_to_s(options[:method]) if options[:method]
+          js_options['insertion']    = "'#{options[:position].to_s.downcase}'" if options[:position]
+          js_options['evalScripts']  = options[:script].nil? || options[:script]
+
+          if options[:form]
+            js_options['parameters'] = 'Form.serialize(this)'
+          elsif options[:submit]
+            js_options['parameters'] = "Form.serialize('#{options[:submit]}')"
+          elsif options[:with]
+            js_options['parameters'] = options[:with]
           end
-          js_options['parameters'] << "#{request_forgery_protection_token}=' + encodeURIComponent('#{escape_javascript form_authenticity_token}')"
-        end
 
-        options_for_javascript(js_options)
-      end
-
-      def method_option_to_s(method)
-        (method.is_a?(String) and !method.index("'").nil?) ? method : "'#{method}'"
-      end
+          if protect_against_forgery? && !options[:form]
+            if js_options['parameters']
+              js_options['parameters'] << " + '&"
+            else
+              js_options['parameters'] = "'"
+            end
+            js_options['parameters'] << "#{request_forgery_protection_token}=' + encodeURIComponent('#{escape_javascript form_authenticity_token}')"
+          end
 
-      def build_observer(klass, name, options = {})
-        if options[:with] && (options[:with] !~ /[\{=(.]/)
-          options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)"
-        else
-          options[:with] ||= 'value' unless options[:function]
+          options_for_javascript(js_options)
         end
 
-        callback = options[:function] || remote_function(options)
-        javascript  = "new #{klass}('#{name}', "
-        javascript << "#{options[:frequency]}, " if options[:frequency]
-        javascript << "function(element, value) {"
-        javascript << "#{callback}}"
-        javascript << ")"
-        javascript_tag(javascript)
-      end
+        def method_option_to_s(method)
+          (method.is_a?(String) and !method.index("'").nil?) ? method : "'#{method}'"
+        end
 
-      def build_callbacks(options)
-        callbacks = {}
-        options.each do |callback, code|
-          if CALLBACKS.include?(callback)
-            name = 'on' + callback.to_s.capitalize
-            callbacks[name] = "function(request){#{code}}"
+        def build_callbacks(options)
+          callbacks = {}
+          options.each do |callback, code|
+            if CALLBACKS.include?(callback)
+              name = 'on' + callback.to_s.capitalize
+              callbacks[name] = "function(request){#{code}}"
+            end
           end
+          callbacks
         end
-        callbacks
-      end
     end
 
     # Converts chained method calls on DOM proxy elements into JavaScript chains
-- 
cgit v1.2.3


From 95f317b0204d63810b837eae48667d9ed311f7dd Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 15:01:02 -0600
Subject: Move periodically_call_remote into prototype_legacy_helper plugin

---
 .../lib/action_view/helpers/prototype_helper.rb    | 35 ----------------------
 1 file changed, 35 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 92f4ca838f..0ec7b48c25 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -39,10 +39,6 @@ module ActionView
     #    <div><%= submit_tag 'Recalculate Shipping' %></div>
     #  <% end -%>
     #
-    # ...periodically...
-    #
-    #  periodically_call_remote(:url => 'update', :frequency => '5', :update => 'ticker')
-    #
     # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than
     # are listed here); check out the documentation for each method to find out more about its usage and options.
     #
@@ -255,37 +251,6 @@ module ActionView
         button_to_function(name, remote_function(options), html_options)
       end
 
-      # Periodically calls the specified url (<tt>options[:url]</tt>) every
-      # <tt>options[:frequency]</tt> seconds (default is 10). Usually used to
-      # update a specified div (<tt>options[:update]</tt>) with the results
-      # of the remote call. The options for specifying the target with <tt>:url</tt>
-      # and defining callbacks is the same as link_to_remote.
-      # Examples:
-      #  # Call get_averages and put its results in 'avg' every 10 seconds
-      #  # Generates:
-      #  #      new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages',
-      #  #      {asynchronous:true, evalScripts:true})}, 10)
-      #  periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg')
-      #
-      #  # Call invoice every 10 seconds with the id of the customer
-      #  # If it succeeds, update the invoice DIV; if it fails, update the error DIV
-      #  # Generates:
-      #  #      new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'},
-      #  #      '/testing/invoice/16', {asynchronous:true, evalScripts:true})}, 10)
-      #  periodically_call_remote(:url => { :action => 'invoice', :id => customer.id },
-      #     :update => { :success => "invoice", :failure => "error" }
-      #
-      #  # Call update every 20 seconds and update the new_block DIV
-      #  # Generates:
-      #  # new PeriodicalExecuter(function() {new Ajax.Updater('news_block', 'update', {asynchronous:true, evalScripts:true})}, 20)
-      #  periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
-      #
-      def periodically_call_remote(options = {})
-         frequency = options[:frequency] || 10 # every ten seconds by default
-         code = "new PeriodicalExecuter(function() {#{remote_function(options)}}, #{frequency})"
-         javascript_tag(code)
-      end
-
       # Returns a form tag that will submit using XMLHttpRequest in the
       # background instead of the regular reloading POST arrangement. Even
       # though it's using JavaScript to serialize the form elements, the form
-- 
cgit v1.2.3


From 2de311a09363f0e7bb4e21cef8e77df7ee92d33f Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 15:08:29 -0600
Subject: Drop AjaxHelper

---
 actionpack/lib/action_view/helpers/ajax_helper.rb | 68 -----------------------
 1 file changed, 68 deletions(-)
 delete mode 100644 actionpack/lib/action_view/helpers/ajax_helper.rb

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/ajax_helper.rb b/actionpack/lib/action_view/helpers/ajax_helper.rb
deleted file mode 100644
index 9cc2acc239..0000000000
--- a/actionpack/lib/action_view/helpers/ajax_helper.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-module ActionView
-  module Helpers
-    module AjaxHelper
-      include UrlHelper
-      
-      def link_to_remote(name, url, options = {})
-        html = options.delete(:html) || {}
-        
-        update = options.delete(:update)
-        if update.is_a?(Hash)
-          html["data-update-success"] = update[:success]
-          html["data-update-failure"] = update[:failure]
-        else
-          html["data-update-success"] = update
-        end
-
-        html["data-update-position"] = options.delete(:position)
-        html["data-method"]          = options.delete(:method)
-        html["data-remote"]          = "true"
-        
-        html.merge!(options)
-        
-        url = url_for(url) if url.is_a?(Hash)
-        link_to(name, url, html)
-      end
-      
-      def button_to_remote(name, options = {}, html_options = {})
-        url = options.delete(:url)
-        url = url_for(url) if url.is_a?(Hash)
-        
-        html_options.merge!(:type => "button", :value => name,
-          :"data-url" => url)
-        
-        tag(:input, html_options)
-      end
-      
-      module Rails2Compatibility
-        def set_callbacks(options, html)
-          [:complete, :failure, :success, :interactive, :loaded, :loading].each do |type|
-            html["data-#{type}-code"]  = options.delete(type.to_sym)
-          end
-
-          options.each do |option, value|
-            if option.is_a?(Integer)
-              html["data-#{option}-code"] = options.delete(option)
-            end
-          end
-        end
-        
-        def link_to_remote(name, url, options = nil)
-          if !options && url.is_a?(Hash) && url.key?(:url)
-            url, options = url.delete(:url), url
-          end
-          
-          set_callbacks(options, options[:html] ||= {})
-          
-          super
-        end
-        
-        def button_to_remote(name, options = {}, html_options = {})
-          set_callbacks(options, html_options)
-          super
-        end
-      end
-      
-    end
-  end
-end
\ No newline at end of file
-- 
cgit v1.2.3


From b3787643ec4b24b4628e29ebccc5fb517b01b824 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 15:20:00 -0600
Subject: Move link_to_function and link_to_remote into prototype_legacy_helper
 plugin

---
 .../lib/action_view/helpers/javascript_helper.rb   |  54 --------
 .../lib/action_view/helpers/prototype_helper.rb    | 141 ---------------------
 .../action_view/helpers/scriptaculous_helper.rb    | 101 +++++++--------
 3 files changed, 48 insertions(+), 248 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index 06a9d3405a..f9249e667d 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -41,60 +41,6 @@ module ActionView
 
       include PrototypeHelper
 
-      # Returns a link of the given +name+ that will trigger a JavaScript +function+ using the
-      # onclick handler and return false after the fact.
-      #
-      # The first argument +name+ is used as the link text.
-      #
-      # 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:
-      #   link_to_function "Greeting", "alert('Hello world!')"
-      #     Produces:
-      #       <a onclick="alert('Hello world!'); return false;" href="#">Greeting</a>
-      #
-      #   link_to_function(image_tag("delete"), "if (confirm('Really?')) do_delete()")
-      #     Produces:
-      #       <a onclick="if (confirm('Really?')) do_delete(); return false;" href="#">
-      #         <img src="/images/delete.png?" alt="Delete"/>
-      #       </a>
-      #
-      #   link_to_function("Show me more", nil, :id => "more_link") do |page|
-      #     page[:details].visual_effect  :toggle_blind
-      #     page[:more_link].replace_html "Show me less"
-      #   end
-      #     Produces:
-      #       <a href="#" id="more_link" onclick="try {
-      #         $(&quot;details&quot;).visualEffect(&quot;toggle_blind&quot;);
-      #         $(&quot;more_link&quot;).update(&quot;Show me less&quot;);
-      #       }
-      #       catch (e) {
-      #         alert('RJS error:\n\n' + e.toString());
-      #         alert('$(\&quot;details\&quot;).visualEffect(\&quot;toggle_blind\&quot;);
-      #         \n$(\&quot;more_link\&quot;).update(\&quot;Show me less\&quot;);');
-      #         throw e
-      #       };
-      #       return false;">Show me more</a>
-      #
-      def link_to_function(name, *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}; return false;"
-        href = html_options[:href] || '#'
-
-        content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick))
-      end
-
       # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
       # onclick handler.
       #
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 0ec7b48c25..56a7198792 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -102,147 +102,6 @@ module ActionView
                          :form, :with, :update, :script, :type ]).merge(CALLBACKS)
       end
 
-      # Returns a link to a remote action defined by <tt>options[:url]</tt>
-      # (using the url_for format) that's called in the background using
-      # XMLHttpRequest. The result of that request can then be inserted into a
-      # DOM object whose id can be specified with <tt>options[:update]</tt>.
-      # Usually, the result would be a partial prepared by the controller with
-      # render :partial.
-      #
-      # Examples:
-      #   # Generates: <a href="#" onclick="new Ajax.Updater('posts', '/blog/destroy/3', {asynchronous:true, evalScripts:true});
-      #   #            return false;">Delete this post</a>
-      #   link_to_remote "Delete this post", :update => "posts",
-      #     :url => { :action => "destroy", :id => post.id }
-      #
-      #   # Generates: <a href="#" onclick="new Ajax.Updater('emails', '/mail/list_emails', {asynchronous:true, evalScripts:true});
-      #   #            return false;"><img alt="Refresh" src="/images/refresh.png?" /></a>
-      #   link_to_remote(image_tag("refresh"), :update => "emails",
-      #     :url => { :action => "list_emails" })
-      #
-      # You can override the generated HTML options by specifying a hash in
-      # <tt>options[:html]</tt>.
-      #
-      #   link_to_remote "Delete this post", :update => "posts",
-      #     :url  => post_url(@post), :method => :delete,
-      #     :html => { :class  => "destructive" }
-      #
-      # You can also specify a hash for <tt>options[:update]</tt> to allow for
-      # easy redirection of output to an other DOM element if a server-side
-      # error occurs:
-      #
-      # Example:
-      #   # Generates: <a href="#" onclick="new Ajax.Updater({success:'posts',failure:'error'}, '/blog/destroy/5',
-      #   #            {asynchronous:true, evalScripts:true}); return false;">Delete this post</a>
-      #   link_to_remote "Delete this post",
-      #     :url => { :action => "destroy", :id => post.id },
-      #     :update => { :success => "posts", :failure => "error" }
-      #
-      # Optionally, you can use the <tt>options[:position]</tt> parameter to
-      # influence how the target DOM element is updated. It must be one of
-      # <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.
-      #
-      # The method used is by default POST. You can also specify GET or you
-      # can simulate PUT or DELETE over POST. All specified with <tt>options[:method]</tt>
-      #
-      # Example:
-      #   # Generates: <a href="#" onclick="new Ajax.Request('/person/4', {asynchronous:true, evalScripts:true, method:'delete'});
-      #   #            return false;">Destroy</a>
-      #   link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
-      #
-      # By default, these remote requests are processed asynchronous during
-      # which various JavaScript callbacks can be triggered (for progress
-      # indicators and the likes). All callbacks get access to the
-      # <tt>request</tt> object, which holds the underlying XMLHttpRequest.
-      #
-      # To access the server response, use <tt>request.responseText</tt>, to
-      # find out the HTTP status, use <tt>request.status</tt>.
-      #
-      # Example:
-      #   # Generates: <a href="#" onclick="new Ajax.Request('/words/undo?n=33', {asynchronous:true, evalScripts:true,
-      #   #            onComplete:function(request){undoRequestCompleted(request)}}); return false;">hello</a>
-      #   word = 'hello'
-      #   link_to_remote word,
-      #     :url => { :action => "undo", :n => word_counter },
-      #     :complete => "undoRequestCompleted(request)"
-      #
-      # The callbacks that may be specified are (in order):
-      #
-      # <tt>:loading</tt>::       Called when the remote document is being
-      #                           loaded with data by the browser.
-      # <tt>:loaded</tt>::        Called when the browser has finished loading
-      #                           the remote document.
-      # <tt>:interactive</tt>::   Called when the user can interact with the
-      #                           remote document, even though it has not
-      #                           finished loading.
-      # <tt>:success</tt>::       Called when the XMLHttpRequest is completed,
-      #                           and the HTTP status code is in the 2XX range.
-      # <tt>:failure</tt>::       Called when the XMLHttpRequest is completed,
-      #                           and the HTTP status code is not in the 2XX
-      #                           range.
-      # <tt>:complete</tt>::      Called when the XMLHttpRequest is complete
-      #                           (fires after success/failure if they are
-      #                           present).
-      #
-      # You can further refine <tt>:success</tt> and <tt>:failure</tt> by
-      # adding additional callbacks for specific status codes.
-      #
-      # Example:
-      #   # Generates: <a href="#" onclick="new Ajax.Request('/testing/action', {asynchronous:true, evalScripts:true,
-      #   #            on404:function(request){alert('Not found...? Wrong URL...?')},
-      #   #            onFailure:function(request){alert('HTTP Error ' + request.status + '!')}}); return false;">hello</a>
-      #   link_to_remote word,
-      #     :url => { :action => "action" },
-      #     404 => "alert('Not found...? Wrong URL...?')",
-      #     :failure => "alert('HTTP Error ' + request.status + '!')"
-      #
-      # A status code callback overrides the success/failure handlers if
-      # present.
-      #
-      # If you for some reason or another need synchronous processing (that'll
-      # block the browser while the request is happening), you can specify
-      # <tt>options[:type] = :synchronous</tt>.
-      #
-      # You can customize further browser side call logic by passing in
-      # JavaScript code snippets via some optional parameters. In their order
-      # of use these are:
-      #
-      # <tt>:confirm</tt>::      Adds confirmation dialog.
-      # <tt>:condition</tt>::    Perform remote request conditionally
-      #                          by this expression. Use this to
-      #                          describe browser-side conditions when
-      #                          request should not be initiated.
-      # <tt>:before</tt>::       Called before request is initiated.
-      # <tt>:after</tt>::        Called immediately after request was
-      #                          initiated and before <tt>:loading</tt>.
-      # <tt>:submit</tt>::       Specifies the DOM element ID that's used
-      #                          as the parent of the form elements. By
-      #                          default this is the current form, but
-      #                          it could just as well be the ID of a
-      #                          table row or any other DOM element.
-      # <tt>:with</tt>::         A JavaScript expression specifying
-      #                          the parameters for the XMLHttpRequest.
-      #                          Any expressions should return a valid
-      #                          URL query string.
-      #
-      #                          Example:
-      #
-      #                            :with => "'name=' + $('name').value"
-      #
-      # You can generate a link that uses AJAX in the general case, while
-      # degrading gracefully to plain link behavior in the absence of
-      # JavaScript by setting <tt>html_options[:href]</tt> to an alternate URL.
-      # Note the extra curly braces around the <tt>options</tt> hash separate
-      # it as the second parameter from <tt>html_options</tt>, the third.
-      #
-      # Example:
-      #   link_to_remote "Delete this post",
-      #     { :update => "posts", :url => { :action => "destroy", :id => post.id } },
-      #     :href => url_for(:action => "destroy", :id => post.id)
-      def link_to_remote(name, options = {}, html_options = nil)
-        link_to_function(name, remote_function(options), html_options || options.delete(:html))
-      end
-
       # Creates a button with an onclick event which calls a remote action
       # via XMLHttpRequest
       # The options for specifying the target with :url
diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
index 04af2781d7..d30164e402 100644
--- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
+++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
@@ -3,11 +3,11 @@ require 'active_support/json'
 
 module ActionView
   module Helpers
-    # Provides a set of helpers for calling Scriptaculous JavaScript 
+    # Provides a set of helpers for calling Scriptaculous JavaScript
     # functions, including those which create Ajax controls and visual effects.
     #
-    # To be able to use these helpers, you must include the Prototype 
-    # JavaScript framework and the Scriptaculous JavaScript library in your 
+    # To be able to use these helpers, you must include the Prototype
+    # JavaScript framework and the Scriptaculous JavaScript library in your
     # pages. See the documentation for ActionView::Helpers::JavaScriptHelper
     # for more information on including the necessary JavaScript.
     #
@@ -18,22 +18,17 @@ module ActionView
       unless const_defined? :TOGGLE_EFFECTS
         TOGGLE_EFFECTS = [:toggle_appear, :toggle_slide, :toggle_blind]
       end
-      
+
       # Returns a JavaScript snippet to be used on the Ajax callbacks for
       # starting visual effects.
       #
-      # Example:
-      #   <%= link_to_remote "Reload", :update => "posts", 
-      #         :url => { :action => "reload" }, 
-      #         :complete => visual_effect(:highlight, "posts", :duration => 0.5)
-      #
       # If no +element_id+ is given, it assumes "element" which should be a local
-      # variable in the generated JavaScript execution context. This can be 
+      # variable in the generated JavaScript execution context. This can be
       # used for example with +drop_receiving_element+:
       #
       #   <%= drop_receiving_element (...), :loading => visual_effect(:fade) %>
       #
-      # This would fade the element that was dropped on the drop receiving 
+      # This would fade the element that was dropped on the drop receiving
       # element.
       #
       # For toggling visual effects, you can use <tt>:toggle_appear</tt>, <tt>:toggle_slide</tt>, and
@@ -44,13 +39,13 @@ module ActionView
       # http://script.aculo.us for more documentation.
       def visual_effect(name, element_id = false, js_options = {})
         element = element_id ? ActiveSupport::JSON.encode(element_id) : "element"
-        
+
         js_options[:queue] = if js_options[:queue].is_a?(Hash)
           '{' + js_options[:queue].map {|k, v| k == :limit ? "#{k}:#{v}" : "#{k}:'#{v}'" }.join(',') + '}'
         elsif js_options[:queue]
           "'#{js_options[:queue]}'"
         end if js_options[:queue]
-        
+
         [:endcolor, :direction, :startcolor, :scaleMode, :restorecolor].each do |option|
           js_options[option] = "'#{js_options[option]}'" if js_options[option]
         end
@@ -61,7 +56,7 @@ module ActionView
           "new Effect.#{name.to_s.camelize}(#{element},#{options_for_javascript(js_options)});"
         end
       end
-      
+
       # Makes the element with the DOM ID specified by +element_id+ sortable
       # by drag-and-drop and make an Ajax call whenever the sort order has
       # changed. By default, the action called gets the serialized sortable
@@ -71,84 +66,84 @@ module ActionView
       #
       #   <%= sortable_element("my_list", :url => { :action => "order" }) %>
       #
-      # In the example, the action gets a "my_list" array parameter 
-      # containing the values of the ids of elements the sortable consists 
+      # In the example, the action gets a "my_list" array parameter
+      # containing the values of the ids of elements the sortable consists
       # of, in the current order.
       #
       # Important: For this to work, the sortable elements must have id
       # attributes in the form "string_identifier". For example, "item_1". Only
       # the identifier part of the id attribute will be serialized.
-      # 
+      #
       # Additional +options+ are:
       #
       # * <tt>:format</tt> - A regular expression to determine what to send as the
       #   serialized id to the server (the default is <tt>/^[^_]*_(.*)$/</tt>).
-      #                           
+      #
       # * <tt>:constraint</tt> - Whether to constrain the dragging to either
       #   <tt>:horizontal</tt> or <tt>:vertical</tt> (or false to make it unconstrained).
-      #                            
+      #
       # * <tt>:overlap</tt> - Calculate the item overlap in the <tt>:horizontal</tt>
       #   or <tt>:vertical</tt> direction.
-      #                            
+      #
       # * <tt>:tag</tt> - Which children of the container element to treat as
       #   sortable (default is <tt>li</tt>).
-      #                          
+      #
       # * <tt>:containment</tt> - Takes an element or array of elements to treat as
       #   potential drop targets (defaults to the original target element).
-      #                          
+      #
       # * <tt>:only</tt> - A CSS class name or array of class names used to filter
       #   out child elements as candidates.
-      #                          
+      #
       # * <tt>:scroll</tt> - Determines whether to scroll the list during drag
       #   operations if the list runs past the visual border.
-      #                          
+      #
       # * <tt>:tree</tt> - Determines whether to treat nested lists as part of the
       #   main sortable list. This means that you can create multi-layer lists,
       #   and not only sort items at the same level, but drag and sort items
       #   between levels.
-      #                          
+      #
       # * <tt>:hoverclass</tt> - If set, the Droppable will have this additional CSS class
-      #   when an accepted Draggable is hovered over it.                         
-      #                          
+      #   when an accepted Draggable is hovered over it.
+      #
       # * <tt>:handle</tt> - Sets whether the element should only be draggable by an
       #   embedded handle. The value may be a string referencing a CSS class value
       #   (as of script.aculo.us V1.5). The first child/grandchild/etc. element
       #   found within the element that has this CSS class value will be used as
       #   the handle.
-      #                          
+      #
       # * <tt>:ghosting</tt> - Clones the element and drags the clone, leaving
       #   the original in place until the clone is dropped (default is <tt>false</tt>).
-      #                          
+      #
       # * <tt>:dropOnEmpty</tt> - If true the Sortable container will be made into
       #   a Droppable, that can receive a Draggable (as according to the containment
       #   rules) as a child element when there are no more elements inside (default
       #   is <tt>false</tt>).
-      #                          
+      #
       # * <tt>:onChange</tt> - Called whenever the sort order changes while dragging. When
       #   dragging from one Sortable to another, the callback is called once on each
       #   Sortable. Gets the affected element as its parameter.
-      #                          
+      #
       # * <tt>:onUpdate</tt> - Called when the drag ends and the Sortable's order is
       #   changed in any way. When dragging from one Sortable to another, the callback
       #   is called once on each Sortable. Gets the container as its parameter.
-      #                                                                                         
+      #
       # See http://script.aculo.us for more documentation.
       def sortable_element(element_id, options = {})
         javascript_tag(sortable_element_js(element_id, options).chop!)
       end
-      
+
       def sortable_element_js(element_id, options = {}) #:nodoc:
         options[:with]     ||= "Sortable.serialize(#{ActiveSupport::JSON.encode(element_id)})"
         options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
         options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
-  
+
         [:tag, :overlap, :constraint, :handle].each do |option|
           options[option] = "'#{options[option]}'" if options[option]
         end
-  
+
         options[:containment] = array_or_string_for_javascript(options[:containment]) if options[:containment]
         options[:only] = array_or_string_for_javascript(options[:only]) if options[:only]
-  
+
         %(Sortable.create(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
       end
 
@@ -156,24 +151,24 @@ module ActionView
       #
       # Example:
       #   <%= draggable_element("my_image", :revert => true)
-      # 
+      #
       # You can change the behaviour with various options, see
       # http://script.aculo.us for more documentation.
       def draggable_element(element_id, options = {})
         javascript_tag(draggable_element_js(element_id, options).chop!)
       end
-      
+
       def draggable_element_js(element_id, options = {}) #:nodoc:
         %(new Draggable(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
       end
 
       # Makes the element with the DOM ID specified by +element_id+ receive
       # dropped draggable elements (created by +draggable_element+).
-      # and make an AJAX call. By default, the action called gets the DOM ID 
+      # and make an AJAX call. By default, the action called gets the DOM ID
       # of the element as parameter.
       #
       # Example:
-      #   <%= drop_receiving_element("my_cart", :url => 
+      #   <%= drop_receiving_element("my_cart", :url =>
       #     { :controller => "cart", :action => "add" }) %>
       #
       # You can change the behaviour with various options, see
@@ -181,41 +176,41 @@ module ActionView
       #
       # Some of these +options+ include:
       # * <tt>:accept</tt> - Set this to a string or an array of strings describing the
-      #   allowable CSS classes that the +draggable_element+ must have in order 
+      #   allowable CSS classes that the +draggable_element+ must have in order
       #   to be accepted by this +drop_receiving_element+.
-      #                          
+      #
       # * <tt>:confirm</tt> - Adds a confirmation dialog. Example:
-      #                     
+      #
       #     :confirm => "Are you sure you want to do this?"
-      #                          
+      #
       # * <tt>:hoverclass</tt> - If set, the +drop_receiving_element+ will have
       #   this additional CSS class when an accepted +draggable_element+ is
-      #   hovered over it.                         
-      #                          
+      #   hovered over it.
+      #
       # * <tt>:onDrop</tt> - Called when a +draggable_element+ is dropped onto
-      #   this element. Override this callback with a JavaScript expression to 
+      #   this element. Override this callback with a JavaScript expression to
       #   change the default drop behaviour. Example:
-      #                          
+      #
       #     :onDrop => "function(draggable_element, droppable_element, event) { alert('I like bananas') }"
-      #                          
+      #
       #   This callback gets three parameters: The Draggable element, the Droppable
       #   element and the Event object. You can extract additional information about
       #   the drop - like if the Ctrl or Shift keys were pressed - from the Event object.
-      #                          
+      #
       # * <tt>:with</tt> - A JavaScript expression specifying the parameters for
       #   the XMLHttpRequest. Any expressions should return a valid URL query string.
       def drop_receiving_element(element_id, options = {})
         javascript_tag(drop_receiving_element_js(element_id, options).chop!)
       end
-      
+
       def drop_receiving_element_js(element_id, options = {}) #:nodoc:
         options[:with]     ||= "'id=' + encodeURIComponent(element.id)"
         options[:onDrop]   ||= "function(element){" + remote_function(options) + "}"
         options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
 
-        options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]    
+        options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]
         options[:hoverclass] = "'#{options[:hoverclass]}'" if options[:hoverclass]
-        
+
         # Confirmation happens during the onDrop callback, so it can be removed from the options
         options.delete(:confirm) if options[:confirm]
 
-- 
cgit v1.2.3


From 779094a6024c762b3dfb60db7efb1d5d7f0c4ddc Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 15:28:31 -0600
Subject: Move button_to_remote and submit_to_remote into
 prototype_legacy_helper plugin

---
 .../lib/action_view/helpers/prototype_helper.rb    | 38 ----------------------
 1 file changed, 38 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 56a7198792..818412c345 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -102,14 +102,6 @@ module ActionView
                          :form, :with, :update, :script, :type ]).merge(CALLBACKS)
       end
 
-      # Creates a button with an onclick event which calls a remote action
-      # via XMLHttpRequest
-      # The options for specifying the target with :url
-      # and defining callbacks is the same as link_to_remote.
-      def button_to_remote(name, options = {}, html_options = {})
-        button_to_function(name, remote_function(options), html_options)
-      end
-
       # Returns a form tag that will submit using XMLHttpRequest in the
       # background instead of the regular reloading POST arrangement. Even
       # though it's using JavaScript to serialize the form elements, the form
@@ -212,36 +204,6 @@ module ActionView
       end
       alias_method :form_remote_for, :remote_form_for
 
-      # Returns a button input tag with the element name of +name+ and a value (i.e., display text) of +value+
-      # that will submit form using XMLHttpRequest in the background instead of a regular POST request that
-      # reloads the page.
-      #
-      #  # Create a button that submits to the create action
-      #  #
-      #  # Generates: <input name="create_btn" onclick="new Ajax.Request('/testing/create',
-      #  #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
-      #  #     return false;" type="button" value="Create" />
-      #  <%= submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %>
-      #
-      #  # Submit to the remote action update and update the DIV succeed or fail based
-      #  # on the success or failure of the request
-      #  #
-      #  # Generates: <input name="update_btn" onclick="new Ajax.Updater({success:'succeed',failure:'fail'},
-      #  #      '/testing/update', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
-      #  #      return false;" type="button" value="Update" />
-      #  <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' },
-      #     :update => { :success => "succeed", :failure => "fail" }
-      #
-      # <tt>options</tt> argument is the same as in form_remote_tag.
-      def submit_to_remote(name, value, options = {})
-        options[:with] ||= 'Form.serialize(this.form)'
-
-        html_options = options.delete(:html) || {}
-        html_options[:name] = name
-
-        button_to_remote(value, options, html_options)
-      end
-
       # Returns '<tt>eval(request.responseText)</tt>' which is the JavaScript function
       # that +form_remote_tag+ can call in <tt>:complete</tt> to evaluate a multiple
       # update return document using +update_element_function+ calls.
-- 
cgit v1.2.3


From 9c2c307ee48b91177c3e1cb8831afe4f972d19eb Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 15:42:30 -0600
Subject: Move form_remote_tag and remote_form_for into prototype_legacy_helper

---
 .../lib/action_view/helpers/prototype_helper.rb    | 109 ---------------------
 1 file changed, 109 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 818412c345..1fa2fed460 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -102,115 +102,6 @@ module ActionView
                          :form, :with, :update, :script, :type ]).merge(CALLBACKS)
       end
 
-      # Returns a form tag that will submit using XMLHttpRequest in the
-      # background instead of the regular reloading POST arrangement. 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>). The options for
-      # specifying the target with <tt>:url</tt> and defining callbacks is the same as
-      # +link_to_remote+.
-      #
-      # A "fall-through" target for browsers that doesn't do JavaScript can be
-      # specified with the <tt>:action</tt>/<tt>:method</tt> options on <tt>:html</tt>.
-      #
-      # Example:
-      #   # Generates:
-      #   #      <form action="/some/place" method="post" onsubmit="new Ajax.Request('',
-      #   #      {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
-      #   form_remote_tag :html => { :action =>
-      #     url_for(:controller => "some", :action => "place") }
-      #
-      # The Hash passed to the <tt>:html</tt> key is equivalent to the options (2nd)
-      # argument in the FormTagHelper.form_tag method.
-      #
-      # By default the fall-through action is the same as the one specified in
-      # the <tt>:url</tt> (and the default method is <tt>:post</tt>).
-      #
-      # form_remote_tag also takes a block, like form_tag:
-      #   # Generates:
-      #   #     <form action="/" method="post" onsubmit="new Ajax.Request('/',
-      #   #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});
-      #   #     return false;"> <div><input name="commit" type="submit" value="Save" /></div>
-      #   #     </form>
-      #   <% form_remote_tag :url => '/posts' do -%>
-      #     <div><%= submit_tag 'Save' %></div>
-      #   <% end -%>
-      def form_remote_tag(options = {}, &block)
-        options[:form] = true
-
-        options[:html] ||= {}
-        options[:html][:onsubmit] =
-          (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
-          "#{remote_function(options)}; return false;"
-
-        form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
-      end
-
-      # Creates a form that will submit using XMLHttpRequest in the background
-      # instead of the regular reloading POST arrangement and a scope around a
-      # specific resource that is used as a base for questioning about
-      # values for the fields.
-      #
-      # === Resource
-      #
-      # Example:
-      #   <% remote_form_for(@post) do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # This will expand to be the same as:
-      #
-      #   <% remote_form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # === Nested Resource
-      #
-      # Example:
-      #   <% remote_form_for([@post, @comment]) do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # This will expand to be the same as:
-      #
-      #   <% remote_form_for :comment, @comment, :url => post_comment_path(@post, @comment), :html => { :method => :put, :class => "edit_comment", :id => "edit_comment_45" } do |f| %>
-      #     ...
-      #   <% end %>
-      #
-      # If you don't need to attach a form to a resource, then check out form_remote_tag.
-      #
-      # See FormHelper#form_for for additional semantics.
-      def remote_form_for(record_or_name_or_array, *args, &proc)
-        options = args.extract_options!
-
-        case record_or_name_or_array
-        when String, Symbol
-          object_name = record_or_name_or_array
-        when Array
-          object = record_or_name_or_array.last
-          object_name = ActionController::RecordIdentifier.singular_class_name(object)
-          apply_form_for_options!(record_or_name_or_array, options)
-          args.unshift object
-        else
-          object      = record_or_name_or_array
-          object_name = ActionController::RecordIdentifier.singular_class_name(record_or_name_or_array)
-          apply_form_for_options!(object, options)
-          args.unshift object
-        end
-
-        concat(form_remote_tag(options))
-        fields_for(object_name, *(args << options), &proc)
-        concat('</form>'.html_safe!)
-      end
-      alias_method :form_remote_for, :remote_form_for
-
-      # Returns '<tt>eval(request.responseText)</tt>' which is the JavaScript function
-      # that +form_remote_tag+ can call in <tt>:complete</tt> to evaluate a multiple
-      # update return document using +update_element_function+ calls.
-      def evaluate_remote_response
-        "eval(request.responseText)"
-      end
-
       # Returns the JavaScript needed for a remote function.
       # Takes the same arguments as link_to_remote.
       #
-- 
cgit v1.2.3


From ad1924125d0aedec9d4555e1e13247e84d65fa01 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 16:02:26 -0600
Subject: Move scripty JSG helpers into scriptaculous_helper.rb

---
 .../lib/action_view/helpers/prototype_helper.rb    | 26 ------------------
 .../action_view/helpers/scriptaculous_helper.rb    | 32 ++++++++++++++++++++++
 2 files changed, 32 insertions(+), 26 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 1fa2fed460..a8fba91354 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -519,32 +519,6 @@ module ActionView
             record "}, #{(seconds * 1000).to_i})"
           end
 
-          # Starts a script.aculo.us visual effect. See
-          # ActionView::Helpers::ScriptaculousHelper for more information.
-          def visual_effect(name, id = nil, options = {})
-            record @context.send(:visual_effect, name, id, options)
-          end
-
-          # Creates a script.aculo.us sortable element. Useful
-          # to recreate sortable elements after items get added
-          # or deleted.
-          # See ActionView::Helpers::ScriptaculousHelper for more information.
-          def sortable(id, options = {})
-            record @context.send(:sortable_element_js, id, options)
-          end
-
-          # Creates a script.aculo.us draggable element.
-          # See ActionView::Helpers::ScriptaculousHelper for more information.
-          def draggable(id, options = {})
-            record @context.send(:draggable_element_js, id, options)
-          end
-
-          # Creates a script.aculo.us drop receiving element.
-          # See ActionView::Helpers::ScriptaculousHelper for more information.
-          def drop_receiving(id, options = {})
-            record @context.send(:drop_receiving_element_js, id, options)
-          end
-
           private
             def loop_on_multiple_args(method, ids)
               record(ids.size>1 ?
diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
index d30164e402..189c14c97a 100644
--- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
+++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
@@ -217,5 +217,37 @@ module ActionView
         %(Droppables.add(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
       end
     end
+
+    module PrototypeHelper
+      class JavaScriptGenerator
+        module GeneratorMethods
+          # Starts a script.aculo.us visual effect. See
+          # ActionView::Helpers::ScriptaculousHelper for more information.
+          def visual_effect(name, id = nil, options = {})
+            record @context.send(:visual_effect, name, id, options)
+          end
+
+          # Creates a script.aculo.us sortable element. Useful
+          # to recreate sortable elements after items get added
+          # or deleted.
+          # See ActionView::Helpers::ScriptaculousHelper for more information.
+          def sortable(id, options = {})
+            record @context.send(:sortable_element_js, id, options)
+          end
+
+          # Creates a script.aculo.us draggable element.
+          # See ActionView::Helpers::ScriptaculousHelper for more information.
+          def draggable(id, options = {})
+            record @context.send(:draggable_element_js, id, options)
+          end
+
+          # Creates a script.aculo.us drop receiving element.
+          # See ActionView::Helpers::ScriptaculousHelper for more information.
+          def drop_receiving(id, options = {})
+            record @context.send(:drop_receiving_element_js, id, options)
+          end
+        end
+      end
+    end
   end
 end
-- 
cgit v1.2.3


From ff3f779629ef0d987642222ff2c74271b029e996 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 16:04:58 -0600
Subject: Unused JAVASCRIPT_PATH const

---
 actionpack/lib/action_view/helpers/javascript_helper.rb | 4 ----
 1 file changed, 4 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index f9249e667d..c84bd2ce96 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -35,10 +35,6 @@ module ActionView
     # For documentation on +javascript_include_tag+ see
     # ActionView::Helpers::AssetTagHelper.
     module JavaScriptHelper
-      unless const_defined? :JAVASCRIPT_PATH
-        JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts')
-      end
-
       include PrototypeHelper
 
       # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
-- 
cgit v1.2.3


From 570e02c96a12ad06888b4ba8d6d8bd3262705dcf Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 16:08:56 -0600
Subject: Move button_to_function to prototype helper

---
 .../lib/action_view/helpers/javascript_helper.rb   | 33 ----------------------
 .../lib/action_view/helpers/prototype_helper.rb    | 33 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 33 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index c84bd2ce96..19243f092a 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -37,39 +37,6 @@ module ActionView
     module JavaScriptHelper
       include PrototypeHelper
 
-      # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
-      # onclick handler.
-      #
-      # The first argument +name+ is used as the button's value or display text.
-      #
-      # 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", "alert('Hello world!')"
-      #   button_to_function "Delete", "if (confirm('Really?')) do_delete()"
-      #   button_to_function "Details" do |page|
-      #     page[:details].visual_effect :toggle_slide
-      #   end
-      #   button_to_function "Details", :class => "details_button" do |page|
-      #     page[:details].visual_effect :toggle_slide
-      #   end
-      def button_to_function(name, *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};"
-
-        tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
-      end
-
       JS_ESCAPE_MAP = {
         '\\'    => '\\\\',
         '</'    => '<\/',
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index a8fba91354..4a32875e00 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -102,6 +102,39 @@ module ActionView
                          :form, :with, :update, :script, :type ]).merge(CALLBACKS)
       end
 
+      # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
+      # onclick handler.
+      #
+      # The first argument +name+ is used as the button's value or display text.
+      #
+      # 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", "alert('Hello world!')"
+      #   button_to_function "Delete", "if (confirm('Really?')) do_delete()"
+      #   button_to_function "Details" do |page|
+      #     page[:details].visual_effect :toggle_slide
+      #   end
+      #   button_to_function "Details", :class => "details_button" do |page|
+      #     page[:details].visual_effect :toggle_slide
+      #   end
+      def button_to_function(name, *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};"
+
+        tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
+      end
+
       # Returns the JavaScript needed for a remote function.
       # Takes the same arguments as link_to_remote.
       #
-- 
cgit v1.2.3


From 657d85580e914caf368a8a12ff5642e4d979ab7e Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 16:13:49 -0600
Subject: Reorg options_for_javascript and array_or_string_for_javascript

---
 actionpack/lib/action_view/helpers/javascript_helper.rb | 17 -----------------
 actionpack/lib/action_view/helpers/prototype_helper.rb  |  8 ++++++++
 .../lib/action_view/helpers/scriptaculous_helper.rb     |  9 +++++++++
 3 files changed, 17 insertions(+), 17 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index 19243f092a..7dca9849c0 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -95,23 +95,6 @@ module ActionView
       def javascript_cdata_section(content) #:nodoc:
         "\n//#{cdata_section("\n#{content}\n//")}\n"
       end
-
-      protected
-        def options_for_javascript(options)
-          if options.empty?
-            '{}'
-          else
-            "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
-          end
-        end
-
-        def array_or_string_for_javascript(option)
-          if option.kind_of?(Array)
-            "['#{option.join('\',\'')}']"
-          elsif !option.nil?
-            "'#{option}'"
-          end
-        end
     end
   end
 end
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 4a32875e00..d335d89274 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -624,6 +624,14 @@ module ActionView
       end
 
       protected
+        def options_for_javascript(options)
+          if options.empty?
+            '{}'
+          else
+            "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
+          end
+        end
+
         def options_for_ajax(options)
           js_options = build_callbacks(options)
 
diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
index 189c14c97a..37319cca1b 100644
--- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
+++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
@@ -216,6 +216,15 @@ module ActionView
 
         %(Droppables.add(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
       end
+
+      protected
+        def array_or_string_for_javascript(option)
+          if option.kind_of?(Array)
+            "['#{option.join('\',\'')}']"
+          elsif !option.nil?
+            "'#{option}'"
+          end
+        end
     end
 
     module PrototypeHelper
-- 
cgit v1.2.3


From 7d9ed8eec1c899dac10d582ced07149fe5c58c4f Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 19:20:49 -0600
Subject: Include prototype ujs adapter with new apps

---
 actionpack/lib/action_view/helpers/asset_tag_helper.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 83357dd76f..4df99f8293 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -140,7 +140,7 @@ module ActionView
         :stylesheets_dir => "#{assets_dir}/stylesheets",
       }
 
-      JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
+      JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
 
       # Returns a link tag that browsers and news readers can use to auto-detect
       # an RSS or ATOM feed. The +type+ can either be <tt>:rss</tt> (default) or
-- 
cgit v1.2.3


From 392817cf11e2e840eb564dd4f8713092cff167f8 Mon Sep 17 00:00:00 2001
From: "Erik St. Martin" <alakriti@gmail.com>
Date: Sat, 30 Jan 2010 19:44:35 -0600
Subject: updating link_to and button_to to support :remote => true and other
 options such as :confirm in a unobtrusive manor

Signed-off-by: Joshua Peek <josh@joshpeek.com>
---
 .../lib/action_view/helpers/form_tag_helper.rb     | 12 ++--
 actionpack/lib/action_view/helpers/url_helper.rb   | 77 +++++++++++++---------
 2 files changed, 51 insertions(+), 38 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 048bedc7ba..0e034d781a 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -57,7 +57,7 @@ module ActionView
       # ==== Examples
       #   select_tag "people", options_from_collection_for_select(@people, "name", "id")
       #   # <select id="people" name="people"><option value="1">David</option></select>
-      #   
+      #
       #   select_tag "people", "<option>David</option>"
       #   # => <select id="people" name="people"><option>David</option></select>
       #
@@ -128,7 +128,7 @@ module ActionView
 
       # Creates a label field
       #
-      # ==== Options  
+      # ==== Options
       # * Creates standard HTML attributes for the tag.
       #
       # ==== Examples
@@ -367,7 +367,7 @@ module ActionView
         if disable_with = options.delete("disable_with")
           disable_with = "this.value='#{disable_with}'"
           disable_with << ";#{options.delete('onclick')}" if options['onclick']
-          
+
           options["onclick"]  = "if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }"
           options["onclick"] << "else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';"
           options["onclick"] << "hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }"
@@ -377,8 +377,7 @@ module ActionView
         end
 
         if confirm = options.delete("confirm")
-          options["onclick"] ||= 'return true;'
-          options["onclick"] = "if (!#{confirm_javascript_function(confirm)}) return false; #{options['onclick']}"
+          add_confirm_to_attributes!(options, confirm)
         end
 
         tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys)
@@ -411,8 +410,7 @@ module ActionView
         options.stringify_keys!
 
         if confirm = options.delete("confirm")
-          options["onclick"] ||= ''
-          options["onclick"] += "return #{confirm_javascript_function(confirm)};"
+          add_confirm_to_attributes!(options, confirm)
         end
 
         tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options.stringify_keys)
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index d6bfc6d4c9..9e52275537 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -218,11 +218,11 @@ module ActionView
           html_options = args[2]
 
           url = url_for(options)
+          html_options = convert_options_to_data_attributes(options, html_options)
 
           if html_options
             html_options = html_options.stringify_keys
             href = html_options['href']
-            convert_options_to_javascript!(html_options, url)
             tag_options = tag_options(html_options)
           else
             tag_options = nil
@@ -291,14 +291,10 @@ module ActionView
           request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
         end
 
-        if confirm = html_options.delete("confirm")
-          html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
-        end
-
         url = options.is_a?(String) ? options : self.url_for(options)
         name ||= url
 
-        convert_options_to_javascript!(html_options, url)
+        html_options = convert_options_to_data_attributes(options, html_options)
 
         html_options.merge!("type" => "submit", "value" => name)
 
@@ -551,46 +547,65 @@ module ActionView
       end
 
       private
-        def convert_options_to_javascript!(html_options, url = '')
+        def convert_options_to_data_attributes(options, html_options)
+          html_options = {} if html_options.nil?
+          html_options = html_options.stringify_keys
+
+          if (options.is_a?(Hash) && options.key?('remote')) || (html_options.is_a?(Hash) && html_options.key?('remote'))
+            html_options['data-remote'] = 'true'
+            options.delete('remote') if options.is_a?(Hash)
+            html_options.delete('remote') if html_options.is_a?(Hash)
+          end
+
           confirm = html_options.delete("confirm")
-          method, href = html_options.delete("method"), html_options['href']
 
           if html_options.key?("popup")
             ActiveSupport::Deprecation.warn(":popup has been deprecated", caller)
           end
 
-          html_options["onclick"] = case
-            when confirm && method
-              "if (#{confirm_javascript_function(confirm)}) { #{method_javascript_function(method, url, href)} };return false;"
-            when confirm
-              "return #{confirm_javascript_function(confirm)};"
-            when method
-              "#{method_javascript_function(method, url, href)}return false;"
-            else
-              html_options["onclick"]
+          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
+
+          html_options["data-url"] = options[:url] if options.is_a?(Hash) && options[:url]
+
+          html_options
         end
 
-        def confirm_javascript_function(confirm)
-          "confirm('#{escape_javascript(confirm)}')"
+        def add_confirm_to_attributes!(html_options, confirm)
+          html_options["data-confirm"] = confirm if confirm
         end
 
-        def method_javascript_function(method, url = '', href = nil)
-          action = (href && url.size > 0) ? "'#{url}'" : 'this.href'
-          submit_function =
-            "var f = document.createElement('form'); f.style.display = 'none'; " +
-            "this.parentNode.appendChild(f); f.method = 'POST'; f.action = #{action};"
+        def add_method_to_attributes!(html_options, method)
+          html_options["rel"] = "nofollow" if method && method.to_s.downcase == "delete"
+          html_options["data-method"] = method if method
+        end
 
-          unless method == :post
-            submit_function << "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "
-            submit_function << "m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); f.appendChild(m);"
+        def add_disable_with_to_attributes!(html_options, disable_with)
+          html_options["data-disable-with"] = disable_with if disable_with
+        end
+
+        def options_for_javascript(options)
+          if options.empty?
+            '{}'
+          else
+            "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
           end
+        end
 
-          if protect_against_forgery?
-            submit_function << "var s = document.createElement('input'); s.setAttribute('type', 'hidden'); "
-            submit_function << "s.setAttribute('name', '#{request_forgery_protection_token}'); s.setAttribute('value', '#{escape_javascript form_authenticity_token}'); f.appendChild(s);"
+        def array_or_string_for_javascript(option)
+          if option.kind_of?(Array)
+            "['#{option.join('\',\'')}']"
+          elsif !option.nil?
+            "'#{option}'"
           end
-          submit_function << "f.submit();"
         end
 
         # Processes the +html_options+ hash, converting the boolean
-- 
cgit v1.2.3


From 31820b9dd60dc94744028b41f818f1fdab36e271 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 20:22:15 -0600
Subject: Generate UJS code for :disable_with

---
 actionpack/lib/action_view/helpers/form_tag_helper.rb | 11 +----------
 actionpack/lib/action_view/helpers/url_helper.rb      |  4 ----
 2 files changed, 1 insertion(+), 14 deletions(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 0e034d781a..fb32f78e5b 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -365,15 +365,7 @@ module ActionView
         options.stringify_keys!
 
         if disable_with = options.delete("disable_with")
-          disable_with = "this.value='#{disable_with}'"
-          disable_with << ";#{options.delete('onclick')}" if options['onclick']
-
-          options["onclick"]  = "if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }"
-          options["onclick"] << "else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';"
-          options["onclick"] << "hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }"
-          options["onclick"] << "this.setAttribute('originalValue', this.value);this.disabled = true;#{disable_with};"
-          options["onclick"] << "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());"
-          options["onclick"] << "if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;"
+          options["data-disable-with"] = disable_with if disable_with
         end
 
         if confirm = options.delete("confirm")
@@ -490,7 +482,6 @@ module ActionView
         def sanitize_to_id(name)
           name.to_s.gsub(']','').gsub(/[^-a-zA-Z0-9:.]/, "_")
         end
-
     end
   end
 end
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 9e52275537..7d42a2ef69 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -588,10 +588,6 @@ module ActionView
           html_options["data-method"] = method if method
         end
 
-        def add_disable_with_to_attributes!(html_options, disable_with)
-          html_options["data-disable-with"] = disable_with if disable_with
-        end
-
         def options_for_javascript(options)
           if options.empty?
             '{}'
-- 
cgit v1.2.3


From 48459c82783c53e1ac671259d65c806384f60f2b Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 30 Jan 2010 20:26:30 -0600
Subject: Add rel=nofollow on non get remote links

---
 actionpack/lib/action_view/helpers/url_helper.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'actionpack/lib/action_view/helpers')

diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 7d42a2ef69..bd179ef0b3 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -584,7 +584,7 @@ module ActionView
         end
 
         def add_method_to_attributes!(html_options, method)
-          html_options["rel"] = "nofollow" if method && method.to_s.downcase == "delete"
+          html_options["rel"] = "nofollow" if method && method.to_s.downcase != "get"
           html_options["data-method"] = method if method
         end
 
-- 
cgit v1.2.3