GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Performance: javascript helper tweaks to speed up escaping and reduce 
object allocations when building options strings
jeremy (author)
Sat Jun 21 14:54:10 -0700 2008
commit  f4ccc179530d5b9436da87d3c221dfa8fa89119a
tree    6ace7c7bd35cef137e84057a566cdb97dbf5b53b
parent  9a0e4437199a233105348938e490808fc0688626
...
4
5
6
7
 
8
9
10
 
 
11
12
13
...
20
21
22
23
24
 
 
25
26
27
 
28
29
 
30
31
32
 
 
33
34
35
36
37
38
 
39
40
41
...
43
44
45
46
47
 
 
48
49
50
51
52
 
53
54
55
...
70
71
72
73
74
75
 
 
 
76
77
78
 
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 
 
 
 
 
 
 
95
96
97
 
 
98
99
100
101
102
 
103
104
105
...
111
112
113
114
115
116
117
118
119
120
121
122
 
 
 
 
 
 
123
124
125
 
126
127
128
129
130
131
132
 
133
134
135
136
137
 
 
138
139
 
140
141
142
 
143
144
 
145
146
147
148
149
 
 
 
 
 
 
 
 
 
 
150
151
152
 
 
 
 
 
153
154
155
...
163
164
165
166
 
167
168
169
...
180
181
182
183
 
184
185
 
 
 
 
 
186
187
188
189
190
191
 
192
193
194
 
 
 
 
 
195
196
 
197
198
 
199
200
201
202
203
204
205
206
 
207
208
209
...
4
5
6
 
7
8
 
 
9
10
11
12
13
...
20
21
22
 
 
23
24
25
26
 
27
28
 
29
30
 
 
31
32
33
34
35
36
37
 
38
39
40
41
...
43
44
45
 
 
46
47
48
49
50
51
 
52
53
54
55
...
70
71
72
 
 
 
73
74
75
76
77
 
78
79
80
81
82
 
 
 
 
 
 
 
 
 
 
 
 
83
84
85
86
87
88
89
90
 
 
91
92
93
94
95
96
 
97
98
99
100
...
106
107
108
 
 
 
 
 
 
 
 
 
109
110
111
112
113
114
115
116
 
117
118
119
120
121
122
123
 
124
125
126
127
 
 
128
129
130
 
131
132
133
 
134
135
 
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
 
154
155
156
157
158
159
160
161
...
169
170
171
 
172
173
174
175
...
186
187
188
 
189
190
 
191
192
193
194
195
196
197
198
199
200
 
201
202
203
 
204
205
206
207
208
209
 
210
211
 
212
213
214
215
216
 
217
218
 
219
220
221
222
0
@@ -4,10 +4,10 @@ require 'action_view/helpers/prototype_helper'
0
 module ActionView
0
   module Helpers
0
     # Provides functionality for working with JavaScript in your views.
0
- #
0
+ #
0
     # == Ajax, controls and visual effects
0
- #
0
- # * For information on using Ajax, see
0
+ #
0
+ # * For information on using Ajax, see
0
     # ActionView::Helpers::PrototypeHelper.
0
     # * For information on using controls and visual effects, see
0
     # ActionView::Helpers::ScriptaculousHelper.
0
@@ -20,22 +20,22 @@ module ActionView
0
     # and ActionView::Helpers::ScriptaculousHelper), you must do one of the
0
     # following:
0
     #
0
- # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
0
- # section of your page (recommended): This function will return
0
+ # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
0
+ # section of your page (recommended): This function will return
0
     # references to the JavaScript files created by the +rails+ command in
0
     # your <tt>public/javascripts</tt> directory. Using it is recommended as
0
- # the browser can then cache the libraries instead of fetching all the
0
+ # the browser can then cache the libraries instead of fetching all the
0
     # functions anew on every request.
0
- # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
0
+ # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
0
     # will only include the Prototype core library, which means you are able
0
- # to use all basic AJAX functionality. For the Scriptaculous-based
0
- # JavaScript helpers, like visual effects, autocompletion, drag and drop
0
+ # to use all basic AJAX functionality. For the Scriptaculous-based
0
+ # JavaScript helpers, like visual effects, autocompletion, drag and drop
0
     # and so on, you should use the method described above.
0
     # * Use <tt><%= define_javascript_functions %></tt>: this will copy all the
0
     # JavaScript support functions within a single script block. Not
0
     # recommended.
0
     #
0
- # For documentation on +javascript_include_tag+ see
0
+ # For documentation on +javascript_include_tag+ see
0
     # ActionView::Helpers::AssetTagHelper.
0
     module JavaScriptHelper
0
       unless const_defined? :JAVASCRIPT_PATH
0
@@ -43,13 +43,13 @@ module ActionView
0
       end
0
 
0
       include PrototypeHelper
0
-
0
- # Returns a link that will trigger a JavaScript +function+ using the
0
+
0
+ # Returns a link that will trigger a JavaScript +function+ using the
0
       # onclick handler and return false after the fact.
0
       #
0
       # The +function+ argument can be omitted in favor of an +update_page+
0
       # block, which evaluates to a string when the template is rendered
0
- # (instead of making an Ajax request first).
0
+ # (instead of making an Ajax request first).
0
       #
0
       # Examples:
0
       # link_to_function "Greeting", "alert('Hello world!')"
0
@@ -70,36 +70,31 @@ module ActionView
0
       # <a href="#" id="more_link" onclick="try {
0
       # $(&quot;details&quot;).visualEffect(&quot;toggle_blind&quot;);
0
       # $(&quot;more_link&quot;).update(&quot;Show me less&quot;);
0
- # }
0
- # catch (e) {
0
- # alert('RJS error:\n\n' + e.toString());
0
+ # }
0
+ # catch (e) {
0
+ # alert('RJS error:\n\n' + e.toString());
0
       # alert('$(\&quot;details\&quot;).visualEffect(\&quot;toggle_blind\&quot;);
0
       # \n$(\&quot;more_link\&quot;).update(\&quot;Show me less\&quot;);');
0
- # throw e
0
+ # throw e
0
       # };
0
       # return false;">Show me more</a>
0
       #
0
       def link_to_function(name, *args, &block)
0
- html_options = args.extract_options!
0
- function = args[0] || ''
0
-
0
- html_options.symbolize_keys!
0
- function = update_page(&block) if block_given?
0
- content_tag(
0
- "a", name,
0
- html_options.merge({
0
- :href => html_options[:href] || "#",
0
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;"
0
- })
0
- )
0
+ html_options = args.extract_options!.symbolize_keys!
0
+
0
+ function = block_given? ? update_page(&block) : args[0] || ''
0
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
0
+ href = html_options[:href] || '#'
0
+
0
+ content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick))
0
       end
0
-
0
- # Returns a button that'll trigger a JavaScript +function+ using the
0
+
0
+ # Returns a button that'll trigger a JavaScript +function+ using the
0
       # onclick handler.
0
       #
0
       # The +function+ argument can be omitted in favor of an +update_page+
0
       # block, which evaluates to a string when the template is rendered
0
- # (instead of making an Ajax request first).
0
+ # (instead of making an Ajax request first).
0
       #
0
       # Examples:
0
       # button_to_function "Greeting", "alert('Hello world!')"
0
@@ -111,45 +106,56 @@ module ActionView
0
       # page[:details].visual_effect :toggle_slide
0
       # end
0
       def button_to_function(name, *args, &block)
0
- html_options = args.extract_options!
0
- function = args[0] || ''
0
-
0
- html_options.symbolize_keys!
0
- function = update_page(&block) if block_given?
0
- tag(:input, html_options.merge({
0
- :type => "button", :value => name,
0
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
0
- }))
0
+ html_options = args.extract_options!.symbolize_keys!
0
+
0
+ function = block_given? ? update_page(&block) : args[0] || ''
0
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
0
+
0
+ tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
0
       end
0
 
0
- # Includes the Action Pack JavaScript libraries inside a single <script>
0
+ # Includes the Action Pack JavaScript libraries inside a single <script>
0
       # tag. The function first includes prototype.js and then its core extensions,
0
       # (determined by filenames starting with "prototype").
0
       # Afterwards, any additional scripts will be included in undefined order.
0
       #
0
       # Note: The recommended approach is to copy the contents of
0
       # lib/action_view/helpers/javascripts/ into your application's
0
- # public/javascripts/ directory, and use +javascript_include_tag+ to
0
+ # public/javascripts/ directory, and use +javascript_include_tag+ to
0
       # create remote <script> links.
0
       def define_javascript_functions
0
         javascript = "<script type=\"#{Mime::JS}\">"
0
-
0
- # load prototype.js and its extensions first
0
+
0
+ # load prototype.js and its extensions first
0
         prototype_libs = Dir.glob(File.join(JAVASCRIPT_PATH, 'prototype*')).sort.reverse
0
- prototype_libs.each do |filename|
0
+ prototype_libs.each do |filename|
0
           javascript << "\n" << IO.read(filename)
0
         end
0
-
0
+
0
         # load other libraries
0
- (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename|
0
+ (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename|
0
           javascript << "\n" << IO.read(filename)
0
         end
0
         javascript << '</script>'
0
       end
0
 
0
+
0
+ JS_ESCAPE_MAP = {
0
+ '\\' => '\\\\',
0
+ '</' => '<\/',
0
+ "\r\n" => '\n',
0
+ "\n" => '\n',
0
+ "\r" => '\n',
0
+ '"' => '\\"',
0
+ "'" => "\\'" }
0
+
0
       # Escape carrier returns and single and double quotes for JavaScript segments.
0
       def escape_javascript(javascript)
0
- (javascript || '').gsub('\\','\0\0').gsub('</','<\/').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
0
+ if javascript
0
+ javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
0
+ else
0
+ ''
0
+ end
0
       end
0
 
0
       # Returns a JavaScript tag with the +content+ inside. Example:
0
@@ -163,7 +169,7 @@ module ActionView
0
       # </script>
0
       #
0
       # +html_options+ may be a hash of attributes for the <script> tag. Example:
0
- # javascript_tag "alert('All is good')", :defer => 'defer'
0
+ # javascript_tag "alert('All is good')", :defer => 'defer'
0
       # # => <script defer="defer" type="text/javascript">alert('All is good')</script>
0
       #
0
       # Instead of passing the content as an argument, you can also use a block
0
@@ -180,30 +186,37 @@ module ActionView
0
             content_or_options_with_block
0
           end
0
 
0
- tag = content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
0
+ tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
0
 
0
- block_given? ? concat(tag) : tag
0
+ if block_called_from_erb?(block)
0
+ concat(tag)
0
+ else
0
+ tag
0
+ end
0
       end
0
 
0
       def javascript_cdata_section(content) #:nodoc:
0
         "\n//#{cdata_section("\n#{content}\n//")}\n"
0
       end
0
-
0
+
0
     protected
0
       def options_for_javascript(options)
0
- '{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}'
0
+ if options.empty?
0
+ '{}'
0
+ else
0
+ "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
0
+ end
0
       end
0
-
0
+
0
       def array_or_string_for_javascript(option)
0
- js_option = if option.kind_of?(Array)
0
+ if option.kind_of?(Array)
0
           "['#{option.join('\',\'')}']"
0
         elsif !option.nil?
0
           "'#{option}'"
0
         end
0
- js_option
0
       end
0
     end
0
-
0
+
0
     JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper
0
   end
0
 end
...
115
116
117
118
 
119
120
121
...
115
116
117
 
118
119
120
121
0
@@ -115,7 +115,7 @@ module ActionView
0
         # can't take an <% end %> later on, so we have to use <% ... %>
0
         # and implicitly concat.
0
         def block_called_from_erb?(block)
0
- eval(BLOCK_CALLED_FROM_ERB, block)
0
+ block && eval(BLOCK_CALLED_FROM_ERB, block)
0
         end
0
 
0
         def content_tag_string(name, content, options, escape = true)
...
535
536
537
538
 
539
540
541
...
535
536
537
 
538
539
540
541
0
@@ -535,7 +535,7 @@ module ActionView
0
             when method
0
               "#{method_javascript_function(method, url, href)}return false;"
0
             when popup
0
- popup_javascript_function(popup) + 'return false;'
0
+ "#{popup_javascript_function(popup)}return false;"
0
             else
0
               html_options["onclick"]
0
           end

Comments

    No one has commented yet.