require File.dirname(__FILE__) + '/tag_helper' module ActionView module Helpers # Provides a set of helpers for calling Javascript functions and, most importantly, to call remote methods using what has # been labelled Ajax[http://www.adaptivepath.com/publications/essays/archives/000385.php]. This means that you can call # actions in your controllers without reloading the page, but still update certain parts of it using injections into the # DOM. The common use case is having a form that adds a new element to a list without reloading the page. # # To be able to use the Javascript helpers, you must either call <%= define_javascript_functions %> (which returns all # the Javascript support functions in a ' end # Observes the field with the DOM ID specified by +field_id+ and makes # an Ajax when its contents have changed. # # Required +options+ are: # :frequency:: The frequency (in seconds) at which changes to # this field will be detected. # :url:: +url_for+-style options for the action to call # when the field has changed. # # Additional options are: # :update:: Specifies the DOM ID of the element whose # innerHTML should be updated with the # XMLHttpRequest response text. # :with:: A Javascript expression specifying the # parameters for the XMLHttpRequest. This defaults # to 'value', which in the evaluated context # refers to the new field value. # # Additionally, you may specify any of the options documented in # +link_to_remote. def observe_field(field_id, options = {}) build_observer('Form.Element.Observer', field_id, options) end # Like +observe_field+, but operates on an entire form identified by the # DOM ID +form_id+. +options+ are the same as +observe_field+, except # the default value of the :with option evaluates to the # serialized (request string) value of the form. def observe_form(form_id, options = {}) build_observer('Form.Observer', form_id, options) end # Escape carrier returns and single and double quotes for Javascript segments. def escape_javascript(javascript) (javascript || '').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" } end private def options_for_ajax(options) js_options = build_callbacks(options) js_options['asynchronous'] = options[:type] != :synchronous js_options['method'] = options[:method] if options[:method] js_options['insertion'] = "Insertion.#{options[:position].to_s.camelize}" if options[:position] if options[:form] js_options['parameters'] = 'Form.serialize(this)' elsif options[:with] js_options['parameters'] = options[:with] end '{' + js_options.map {|k, v| "#{k}:#{v}"}.join(', ') + '}' end def build_observer(klass, name, options = {}) options[:with] ||= 'value' if options[:update] callback = remote_function(options) javascript = '" end def build_callbacks(options) CALLBACKS.inject({}) do |callbacks, callback| if options[callback] name = 'on' + callback.to_s.capitalize code = options[callback] callbacks[name] = "function(request){#{code}}" end callbacks end end end end end