Lots going on
[lyrix.git] / vendor / rails / actionpack / lib / action_view / helpers / javascript_helper.rb
blob51cbfb95d935618c51fb7646fced0ce4639ce411
1 require 'action_view/helpers/tag_helper'
2 require 'action_view/helpers/prototype_helper'
4 module ActionView
5   module Helpers
6     # Provides functionality for working with JavaScript in your views.
7     # 
8     # == Ajax, controls and visual effects
9     # 
10     # * For information on using Ajax, see 
11     #   ActionView::Helpers::PrototypeHelper.
12     # * For information on using controls and visual effects, see
13     #   ActionView::Helpers::ScriptaculousHelper.
14     #
15     # == Including the JavaScript libraries into your pages
16     #
17     # Rails includes the Prototype JavaScript framework and the Scriptaculous
18     # JavaScript controls and visual effects library.  If you wish to use
19     # these libraries and their helpers (ActionView::Helpers::PrototypeHelper
20     # and ActionView::Helpers::ScriptaculousHelper), you must do one of the
21     # following:
22     #
23     # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD 
24     #   section of your page (recommended): This function will return 
25     #   references to the JavaScript files created by the +rails+ command in
26     #   your <tt>public/javascripts</tt> directory. Using it is recommended as
27     #   the browser can then cache the libraries instead of fetching all the 
28     #   functions anew on every request.
29     # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but 
30     #   will only include the Prototype core library, which means you are able
31     #   to use all basic AJAX functionality. For the Scriptaculous-based 
32     #   JavaScript helpers, like visual effects, autocompletion, drag and drop 
33     #   and so on, you should use the method described above.
34     # * Use <tt><%= define_javascript_functions %></tt>: this will copy all the
35     #   JavaScript support functions within a single script block. Not
36     #   recommended.
37     #
38     # For documentation on +javascript_include_tag+ see 
39     # ActionView::Helpers::AssetTagHelper.
40     module JavaScriptHelper
41       unless const_defined? :JAVASCRIPT_PATH
42         JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts')
43       end
45       include PrototypeHelper
46       
47       # Returns a link that will trigger a JavaScript +function+ using the 
48       # onclick handler and return false after the fact.
49       #
50       # The +function+ argument can be omitted in favor of an +update_page+
51       # block, which evaluates to a string when the template is rendered
52       # (instead of making an Ajax request first).      
53       #
54       # Examples:
55       #   link_to_function "Greeting", "alert('Hello world!')"
56       #     Produces:
57       #       <a onclick="alert('Hello world!'); return false;" href="#">Greeting</a>
58       #
59       #   link_to_function(image_tag("delete"), "if (confirm('Really?')) do_delete()")
60       #     Produces:
61       #       <a onclick="if (confirm('Really?')) do_delete(); return false;" href="#">
62       #         <img src="/images/delete.png?" alt="Delete"/>
63       #       </a>
64       #
65       #   link_to_function("Show me more", nil, :id => "more_link") do |page|
66       #     page[:details].visual_effect  :toggle_blind
67       #     page[:more_link].replace_html "Show me less"
68       #   end
69       #     Produces:
70       #       <a href="#" id="more_link" onclick="try {
71       #         $(&quot;details&quot;).visualEffect(&quot;toggle_blind&quot;);
72       #         $(&quot;more_link&quot;).update(&quot;Show me less&quot;);
73       #       } 
74       #       catch (e) { 
75       #         alert('RJS error:\n\n' + e.toString()); 
76       #         alert('$(\&quot;details\&quot;).visualEffect(\&quot;toggle_blind\&quot;);
77       #         \n$(\&quot;more_link\&quot;).update(\&quot;Show me less\&quot;);');
78       #         throw e 
79       #       };
80       #       return false;">Show me more</a>
81       #
82       def link_to_function(name, *args, &block)
83         html_options = args.extract_options!
84         function = args[0] || ''
86         html_options.symbolize_keys!
87         function = update_page(&block) if block_given?
88         content_tag(
89           "a", name, 
90           html_options.merge({ 
91             :href => html_options[:href] || "#", 
92             :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;" 
93           })
94         )
95       end
96       
97       # Returns a button that'll trigger a JavaScript +function+ using the 
98       # onclick handler.
99       #
100       # The +function+ argument can be omitted in favor of an +update_page+
101       # block, which evaluates to a string when the template is rendered
102       # (instead of making an Ajax request first).      
103       #
104       # Examples:
105       #   button_to_function "Greeting", "alert('Hello world!')"
106       #   button_to_function "Delete", "if (confirm('Really?')) do_delete()"
107       #   button_to_function "Details" do |page|
108       #     page[:details].visual_effect :toggle_slide
109       #   end
110       #   button_to_function "Details", :class => "details_button" do |page|
111       #     page[:details].visual_effect :toggle_slide
112       #   end
113       def button_to_function(name, *args, &block)
114         html_options = args.extract_options!
115         function = args[0] || ''
117         html_options.symbolize_keys!
118         function = update_page(&block) if block_given?
119         tag(:input, html_options.merge({ 
120           :type => "button", :value => name, 
121           :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" 
122         }))
123       end
125       # Includes the Action Pack JavaScript libraries inside a single <script> 
126       # tag. The function first includes prototype.js and then its core extensions,
127       # (determined by filenames starting with "prototype").
128       # Afterwards, any additional scripts will be included in undefined order.
129       #
130       # Note: The recommended approach is to copy the contents of
131       # lib/action_view/helpers/javascripts/ into your application's
132       # public/javascripts/ directory, and use +javascript_include_tag+ to 
133       # create remote <script> links.
134       def define_javascript_functions
135         javascript = "<script type=\"#{Mime::JS}\">"
136         
137         # load prototype.js and its extensions first 
138         prototype_libs = Dir.glob(File.join(JAVASCRIPT_PATH, 'prototype*')).sort.reverse
139         prototype_libs.each do |filename| 
140           javascript << "\n" << IO.read(filename)
141         end
142         
143         # load other librairies
144         (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename| 
145           javascript << "\n" << IO.read(filename)
146         end
147         javascript << '</script>'
148       end
150       # Escape carrier returns and single and double quotes for JavaScript segments.
151       def escape_javascript(javascript)
152         (javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
153       end
155       # Returns a JavaScript tag with the +content+ inside. Example:
156       #   javascript_tag "alert('All is good')"
157       #
158       # Returns:
159       #
160       #   <script type="text/javascript">
161       #   //<![CDATA[
162       #   alert('All is good')
163       #   //]]>
164       #   </script>
165       #
166       # +html_options+ may be a hash of attributes for the <script> tag. Example:
167       #   javascript_tag "alert('All is good')", :defer => 'true' # => <script defer="true" type="text/javascript">alert('All is good')</script>
168       def javascript_tag(content, html_options = {})
169         content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
170       end
172       def javascript_cdata_section(content) #:nodoc:
173         "\n//#{cdata_section("\n#{content}\n//")}\n"
174       end
175       
176     protected
177       def options_for_javascript(options)
178         '{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}'
179       end
180       
181       def array_or_string_for_javascript(option)
182         js_option = if option.kind_of?(Array)
183           "['#{option.join('\',\'')}']"
184         elsif !option.nil?
185           "'#{option}'"
186         end
187         js_option
188       end
189     end
190     
191     JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper
192   end