require File.dirname(__FILE__) + '/tag_helper' module ActionView module Helpers # You must call <%= define_javascript_functions %> in your application before using these helpers. module JavascriptHelper # Returns a link that'll trigger a javascript +function+ using the onclick handler and return false after the fact. # # Examples: # link_to_function "Greeting", "alert('Hello world!')" # link_to_function(image_tag("delete"), "if confirm('Really?'){ do_delete(); }") def link_to_function(name, function, html_options = {}) content_tag( "a", name, html_options.symbolize_keys.merge(:href => "#", :onclick => "#{function}; return false;") ) end # Returns a link to a remote action defined by options[:url] (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 who's id can be specified # with options[:update]. Usually, the result would be a partial prepared by the controller with either render_partial # or render_partial_collection. # # Examples: # link_to_remote "Delete this post", :update => "posts", :url => { :action => "destroy", :id => post.id } # link_to_remote(image_tag("refresh"), :update => "emails", :url => { :action => "list_emails" }) # # By default, these remote requests are processed asynchronous during which various callbacks can be triggered (for progress indicators # and the likes). # # Example: # link_to_remote word, # :url => { :action => "undo", :n => word_counter }, # :complete => "undoRequestCompleted(request)" # # The complete list of callbacks that may be specified are: # # * :uninitialized -- EXPLAIN ME! # * :loading -- EXPLAIN ME! # * :loaded -- EXPLAIN ME! # * :interactive -- EXPLAIN ME! # * :complete -- EXPLAIN ME! # # If you for some reason or another needs synchronous processing (that'll block the browser while the request is happening), you # can specify options[:type] = :sync. def link_to_remote(name, options = {}, html_options = {}) link_to_function(name, remote_function(options), html_options) end def form_remote_tag(options = {}) options[:form] = true options[:html] ||= { } options[:html][:onsubmit] = "#{remote_function(options)}; return false;" tag("form", options[:html], true) end def remote_function(options) callbacks = build_callbacks(options) function = options[:update] ? "update_with_response('#{options[:update]}', " : "xml_request(" function << "'#{url_for(options[:url])}'" function << ', Form.serialize(this)' if options[:form] function << ', null' if !options[:form] && callbacks function << ", true" if callbacks || options[:type] != :sync function << ", #{callbacks}" if callbacks function << ')' function = "#{options[:before]}; #{function}" if options[:before] function = "#{function}; #{options[:after]}" if options[:after] function = "if (#{options[:condition]}) { #{function}; }" if options[:condition] return function end def define_javascript_functions <<-EOF EOF end private def build_callbacks(options) callbacks = nil %w{uninitialized loading loaded interactive complete}.each do |cb| cb = cb.to_sym if options[cb] callbacks ? callbacks << "," : callbacks = "{" callbacks << "#{cb}:function(request){#{options[cb].gsub(/"/){'\"'}}}" end end callbacks << "}" if callbacks callbacks end end end end