1 require 'action_view/helpers/tag_helper'
2 require 'action_view/helpers/prototype_helper'
6 # Provides functionality for working with JavaScript in your views.
8 # == Ajax, controls and visual effects
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.
15 # == Including the JavaScript libraries into your pages
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
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.
35 # For documentation on +javascript_include_tag+ see
36 # ActionView::Helpers::AssetTagHelper.
37 module JavaScriptHelper
38 unless const_defined
? :JAVASCRIPT_PATH
39 JAVASCRIPT_PATH
= File
.join(File
.dirname(__FILE__
), 'javascripts')
42 include PrototypeHelper
44 # Returns a link of the given +name+ that will trigger a JavaScript +function+ using the
45 # onclick handler and return false after the fact.
47 # The first argument +name+ is used as the link text.
49 # The next arguments are optional and may include the javascript function definition and a hash of html_options.
51 # The +function+ argument can be omitted in favor of an +update_page+
52 # block, which evaluates to a string when the template is rendered
53 # (instead of making an Ajax request first).
55 # The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
57 # 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
61 # link_to_function "Greeting", "alert('Hello world!')"
63 # <a onclick="alert('Hello world!'); return false;" href="#">Greeting</a>
65 # link_to_function(image_tag("delete"), "if (confirm('Really?')) do_delete()")
67 # <a onclick="if (confirm('Really?')) do_delete(); return false;" href="#">
68 # <img src="/images/delete.png?" alt="Delete"/>
71 # link_to_function("Show me more", nil, :id => "more_link") do |page|
72 # page[:details].visual_effect :toggle_blind
73 # page[:more_link].replace_html "Show me less"
76 # <a href="#" id="more_link" onclick="try {
77 # $("details").visualEffect("toggle_blind");
78 # $("more_link").update("Show me less");
81 # alert('RJS error:\n\n' + e.toString());
82 # alert('$(\"details\").visualEffect(\"toggle_blind\");
83 # \n$(\"more_link\").update(\"Show me less\");');
86 # return false;">Show me more</a>
88 def link_to_function(name
, *args
, &block
)
89 html_options
= args
.extract_options
!.symbolize_keys
91 function
= block_given
? ? update_page(&block
) : args
[0] || ''
92 onclick
= "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
93 href
= html_options
[:href] || '#'
95 content_tag(:a, name
, html_options
.merge(:href => href
, :onclick => onclick
))
98 # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
101 # The first argument +name+ is used as the button's value or display text.
103 # The next arguments are optional and may include the javascript function definition and a hash of html_options.
105 # The +function+ argument can be omitted in favor of an +update_page+
106 # block, which evaluates to a string when the template is rendered
107 # (instead of making an Ajax request first).
109 # The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
111 # 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
114 # button_to_function "Greeting", "alert('Hello world!')"
115 # button_to_function "Delete", "if (confirm('Really?')) do_delete()"
116 # button_to_function "Details" do |page|
117 # page[:details].visual_effect :toggle_slide
119 # button_to_function "Details", :class => "details_button" do |page|
120 # page[:details].visual_effect :toggle_slide
122 def button_to_function(name
, *args
, &block
)
123 html_options
= args
.extract_options
!.symbolize_keys
125 function
= block_given
? ? update_page(&block
) : args
[0] || ''
126 onclick
= "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
128 tag(:input, html_options
.merge(:type => 'button', :value => name
, :onclick => onclick
))
140 # Escape carrier returns and single and double quotes for JavaScript segments.
141 def escape_javascript(javascript
)
143 javascript
.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
149 # Returns a JavaScript tag with the +content+ inside. Example:
150 # javascript_tag "alert('All is good')"
153 # <script type="text
/javascript
">
155 # alert('All is good')
159 # +html_options+ may be a hash of attributes for the <script> tag. Example:
160 # javascript_tag "alert('All is good')", :defer => 'defer'
161 # # => <script defer="defer
" type="text
/javascript">alert('All is good')</script
>
163 # Instead of passing the content as an argument, you can also use a block
164 # in which case, you pass your +html_options+ as the first parameter.
165 # <% javascript_tag :defer => 'defer' do -%>
166 # alert('All is good')
168 def javascript_tag(content_or_options_with_block
= nil, html_options
= {}, &block
)
171 html_options
= content_or_options_with_block
if content_or_options_with_block
.is_a
?(Hash
)
174 content_or_options_with_block
177 tag
= content_tag(:script, javascript_cdata_section(content
), html_options
.merge(:type => Mime
::JS))
179 if block_called_from_erb
?(block
)
186 def javascript_cdata_section(content
) #:nodoc:
187 "\n//#{cdata_section("\n#{content}\n//")}\n"
191 def options_for_javascript(options
)
195 "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
199 def array_or_string_for_javascript(option
)
200 if option
.kind_of
?(Array
)
201 "['#{option.join('\',\'')}']"