aboutsummaryrefslogblamecommitdiffstats
path: root/actionpack/lib/action_view/helpers/ajax_helper.rb
blob: 4081117ad1dcee8d173350df609eb22285e41722 (plain) (tree)
1
2
3
4
5



                       
 









                                                                                           




                                                              

                                                                       





                                                              
 
                                             
                                      
         
 
                                                                 
                                                                           
                                                              
                                                               



                               









                                                                              
                                                



                                                          
         
 
                                                    
                                           
                                 
                                                          
 
                                    

         


                                                          



                                    


                                                                 
                                                        

         






                                                                 
                                           










































                                                                                
                                           























                                                                                               
















                                                                                         









                                                                   

       
   
module ActionView
  module Helpers
    module AjaxHelper
      include UrlHelper

      def remote_form_for(record_or_name_or_array, *args, &proc)
        options = args.extract_options!
        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

      def form_remote_tag(options = {}, &block)
        attributes = {}
        attributes.merge!(extract_remote_attributes!(options))
        attributes.merge!(options)

        url = attributes.delete("data-url")
        form_tag(attributes.delete(:action) || url, attributes, &block)
      end

      def link_to_remote(name, url, options = {})
        attributes = {}
        attributes.merge!(extract_remote_attributes!(options))
        attributes.merge!(options)

        url = url_for(url) if url.is_a?(Hash)
        link_to(name, url, attributes)
      end

      def button_to_remote(name, options = {}, html_options = {})
        attributes = html_options.merge!(:type => "button", :value => name)
        attributes.merge!(extract_remote_attributes!(options))
        attributes.merge!(extract_request_attributes!(options))

        tag(:input, attributes)
      end

      def submit_to_remote(name, value, options = {})
        html_options = options.delete(:html) || {}
        html_options.merge!(:name => name, :value => value, :type => "submit")

        attributes = extract_remote_attributes!(options)
        attributes.merge!(html_options)

        tag(:input, attributes)
      end

      def periodically_call_remote(options = {})
        attributes = extract_observer_attributes!(options)
        attributes["data-js-type"] = "periodical_executer"

        script_decorator(attributes)
      end

      #TODO: Should name change to a css query? - BR
      def observe_field(name, options = {})
        options[:observed] = name
        attributes = extract_observer_attributes!(options)

        script_decorator(attributes)
      end

      def observe_form(name, options = {})
        options[:observed] = name
        attributes = extract_observer_attributes!(options)

        script_decorator(attributes)
      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 

          attributes
        end

        def extract_request_attributes!(options)
          attributes = {}
          attributes["data-method"] = options.delete(:method)

          url = options.delete(:url)
          attributes["data-url"] = url.is_a?(Hash) ? url_for(url) : url

          #TODO: Remove all references to prototype - BR
          if options.delete(:form)
            attributes["data-parameters"] = 'Form.serialize(this)'
          elsif submit = options.delete(:submit)
            attributes["data-parameters"] = "Form.serialize('#{submit}')"
          elsif with = options.delete(:with)
            if with !~ /[\{=(.]/
              attributes["data-with"] = "'#{with}=' + encodeURIComponent(value)"
            else
              attributes["data-with"] = with
            end
          end

          purge_unused_attributes!(attributes)
        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
          attributes["data-update-position"] = options.delete(:position)

          purge_unused_attributes!(attributes)
        end

        def extract_observer_attributes!(options)
          attributes = extract_remote_attributes!(options)
          attributes["data-observe"] = true
          attributes["data-observed"] = options.delete(:observed)

          callback = options.delete(:function)
          frequency = options.delete(:frequency)
          if callback
            attributes["data-observer-code"] = create_js_function(callback, "element", "value")
          end
          if frequency && frequency != 0
            attributes["data-frequency"] = frequency.to_i
          end

          purge_unused_attributes!(attributes)
        end

        def purge_unused_attributes!(attributes)
          attributes.delete_if {|key, value| value.nil? }
          attributes
        end

        def create_js_function(statements, *arguments)
          "function(#{arguments.join(", ")}) {#{statements}}"
        end

      # TODO: All evaled goes here per wycat
      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