actionpack 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +17 -0
- data/Rakefile +10 -6
- data/lib/action_controller.rb +0 -0
- data/lib/action_controller/assertions/response_assertions.rb +1 -1
- data/lib/action_controller/assertions/selector_assertions.rb +26 -46
- data/lib/action_controller/base.rb +8 -4
- data/lib/action_controller/dispatcher.rb +1 -1
- data/lib/action_controller/filters.rb +194 -195
- data/lib/action_controller/polymorphic_routes.rb +25 -12
- data/lib/action_controller/record_identifier.rb +20 -13
- data/lib/action_controller/request.rb +9 -6
- data/lib/action_controller/request_profiler.rb +0 -0
- data/lib/action_controller/response.rb +0 -0
- data/lib/action_controller/routing.rb +5 -1
- data/lib/action_controller/routing/builder.rb +1 -2
- data/lib/action_controller/routing/segments.rb +1 -1
- data/lib/action_controller/templates/rescues/layout.erb +1 -1
- data/lib/action_controller/test_process.rb +4 -2
- data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -1
- data/lib/action_controller/verification.rb +1 -1
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view/base.rb +7 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +14 -11
- data/lib/action_view/helpers/date_helper.rb +3 -3
- data/lib/action_view/helpers/form_helper.rb +5 -1
- data/lib/action_view/helpers/form_options_helper.rb +2 -2
- data/lib/action_view/helpers/form_tag_helper.rb +5 -3
- data/lib/action_view/helpers/javascript_helper.rb +4 -4
- data/lib/action_view/helpers/prototype_helper.rb +7 -7
- data/lib/action_view/helpers/tag_helper.rb +4 -3
- data/lib/action_view/helpers/text_helper.rb +1 -1
- data/lib/action_view/helpers/url_helper.rb +3 -5
- data/lib/action_view/partial_template.rb +1 -1
- data/test/controller/action_pack_assertions_test.rb +24 -5
- data/test/controller/assert_select_test.rb +6 -1
- data/test/controller/base_test.rb +37 -1
- data/test/controller/cgi_test.rb +0 -0
- data/test/controller/dispatcher_test.rb +2 -2
- data/test/controller/html-scanner/document_test.rb +25 -0
- data/test/controller/integration_upload_test.rb +1 -1
- data/test/controller/new_render_test.rb +22 -3
- data/test/controller/polymorphic_routes_test.rb +33 -0
- data/test/controller/redirect_test.rb +0 -0
- data/test/controller/render_test.rb +1 -1
- data/test/controller/request_test.rb +6 -0
- data/test/controller/resources_test.rb +15 -17
- data/test/controller/routing_test.rb +22 -2
- data/test/controller/session/cookie_store_test.rb +0 -0
- data/test/controller/test_test.rb +11 -2
- data/test/controller/verification_test.rb +34 -17
- data/test/fixtures/test/render_file_from_template.html.erb +1 -0
- data/test/template/date_helper_test.rb +59 -8
- data/test/template/deprecated_erb_variable_test.rb +9 -0
- data/test/template/form_options_helper_test.rb +505 -514
- data/test/template/form_tag_helper_test.rb +13 -0
- data/test/template/javascript_helper_test.rb +7 -4
- data/test/template/prototype_helper_test.rb +14 -6
- data/test/template/text_helper_test.rb +1 -0
- data/test/template/url_helper_test.rb +11 -1
- metadata +8 -4
@@ -48,6 +48,9 @@ module ActionController
|
|
48
48
|
#
|
49
49
|
# # calls post_url(post)
|
50
50
|
# polymorphic_url(post) # => "http://example.com/posts/1"
|
51
|
+
# polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
|
52
|
+
# polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
|
53
|
+
# polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
|
51
54
|
#
|
52
55
|
# ==== Options
|
53
56
|
#
|
@@ -83,8 +86,6 @@ module ActionController
|
|
83
86
|
else [ record_or_hash_or_array ]
|
84
87
|
end
|
85
88
|
|
86
|
-
args << format if format
|
87
|
-
|
88
89
|
inflection =
|
89
90
|
case
|
90
91
|
when options[:action].to_s == "new"
|
@@ -96,6 +97,9 @@ module ActionController
|
|
96
97
|
else
|
97
98
|
:singular
|
98
99
|
end
|
100
|
+
|
101
|
+
args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
|
102
|
+
args << format if format
|
99
103
|
|
100
104
|
named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options)
|
101
105
|
send!(named_route, *args)
|
@@ -136,11 +140,19 @@ module ActionController
|
|
136
140
|
else
|
137
141
|
record = records.pop
|
138
142
|
route = records.inject("") do |string, parent|
|
139
|
-
|
143
|
+
if parent.is_a?(Symbol) || parent.is_a?(String)
|
144
|
+
string << "#{parent}_"
|
145
|
+
else
|
146
|
+
string << "#{RecordIdentifier.send!("singular_class_name", parent)}_"
|
147
|
+
end
|
140
148
|
end
|
141
149
|
end
|
142
150
|
|
143
|
-
|
151
|
+
if record.is_a?(Symbol) || record.is_a?(String)
|
152
|
+
route << "#{record}_"
|
153
|
+
else
|
154
|
+
route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_"
|
155
|
+
end
|
144
156
|
|
145
157
|
action_prefix(options) + namespace + route + routing_type(options).to_s
|
146
158
|
end
|
@@ -163,16 +175,17 @@ module ActionController
|
|
163
175
|
end
|
164
176
|
end
|
165
177
|
|
178
|
+
# Remove the first symbols from the array and return the url prefix
|
179
|
+
# implied by those symbols.
|
166
180
|
def extract_namespace(record_or_hash_or_array)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
181
|
+
return "" unless record_or_hash_or_array.is_a?(Array)
|
182
|
+
|
183
|
+
namespace_keys = []
|
184
|
+
while (key = record_or_hash_or_array.first) && key.is_a?(String) || key.is_a?(Symbol)
|
185
|
+
namespace_keys << record_or_hash_or_array.shift
|
175
186
|
end
|
187
|
+
|
188
|
+
namespace_keys.map {|k| "#{k}_"}.join
|
176
189
|
end
|
177
190
|
end
|
178
191
|
end
|
@@ -31,18 +31,21 @@ module ActionController
|
|
31
31
|
module RecordIdentifier
|
32
32
|
extend self
|
33
33
|
|
34
|
+
JOIN = '_'.freeze
|
35
|
+
NEW = 'new'.freeze
|
36
|
+
|
34
37
|
# Returns plural/singular for a record or class. Example:
|
35
38
|
#
|
36
39
|
# partial_path(post) # => "posts/post"
|
37
40
|
# partial_path(Person) # => "people/person"
|
38
41
|
# partial_path(Person, "admin/games") # => "admin/people/person"
|
39
42
|
def partial_path(record_or_class, controller_path = nil)
|
40
|
-
|
43
|
+
name = model_name_from_record_or_class(record_or_class)
|
41
44
|
|
42
45
|
if controller_path && controller_path.include?("/")
|
43
|
-
"#{File.dirname(controller_path)}/#{
|
46
|
+
"#{File.dirname(controller_path)}/#{name.partial_path}"
|
44
47
|
else
|
45
|
-
|
48
|
+
name.partial_path
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
@@ -56,21 +59,25 @@ module ActionController
|
|
56
59
|
# dom_class(post, :edit) # => "edit_post"
|
57
60
|
# dom_class(Person, :edit) # => "edit_person"
|
58
61
|
def dom_class(record_or_class, prefix = nil)
|
59
|
-
|
62
|
+
singular = singular_class_name(record_or_class)
|
63
|
+
prefix ? "#{prefix}#{JOIN}#{singular}" : singular
|
60
64
|
end
|
61
65
|
|
62
66
|
# The DOM id convention is to use the singular form of an object or class with the id following an underscore.
|
63
67
|
# If no id is found, prefix with "new_" instead. Examples:
|
64
68
|
#
|
65
|
-
# dom_id(Post.
|
69
|
+
# dom_id(Post.find(45)) # => "post_45"
|
66
70
|
# dom_id(Post.new) # => "new_post"
|
67
71
|
#
|
68
72
|
# If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
|
69
73
|
#
|
70
|
-
# dom_id(Post.
|
74
|
+
# dom_id(Post.find(45), :edit) # => "edit_post_45"
|
71
75
|
def dom_id(record, prefix = nil)
|
72
|
-
|
73
|
-
|
76
|
+
if record_id = record.id
|
77
|
+
"#{dom_class(record, prefix)}#{JOIN}#{record_id}"
|
78
|
+
else
|
79
|
+
dom_class(record, prefix || NEW)
|
80
|
+
end
|
74
81
|
end
|
75
82
|
|
76
83
|
# Returns the plural class name of a record or class. Examples:
|
@@ -78,7 +85,7 @@ module ActionController
|
|
78
85
|
# plural_class_name(post) # => "posts"
|
79
86
|
# plural_class_name(Highrise::Person) # => "highrise_people"
|
80
87
|
def plural_class_name(record_or_class)
|
81
|
-
|
88
|
+
model_name_from_record_or_class(record_or_class).plural
|
82
89
|
end
|
83
90
|
|
84
91
|
# Returns the singular class name of a record or class. Examples:
|
@@ -86,12 +93,12 @@ module ActionController
|
|
86
93
|
# singular_class_name(post) # => "post"
|
87
94
|
# singular_class_name(Highrise::Person) # => "highrise_person"
|
88
95
|
def singular_class_name(record_or_class)
|
89
|
-
|
96
|
+
model_name_from_record_or_class(record_or_class).singular
|
90
97
|
end
|
91
98
|
|
92
99
|
private
|
93
|
-
def
|
94
|
-
record_or_class.is_a?(Class) ? record_or_class : record_or_class.class
|
100
|
+
def model_name_from_record_or_class(record_or_class)
|
101
|
+
(record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
|
95
102
|
end
|
96
103
|
end
|
97
|
-
end
|
104
|
+
end
|
@@ -134,14 +134,17 @@ module ActionController
|
|
134
134
|
# REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma-
|
135
135
|
# delimited list in the case of multiple chained proxies; the last
|
136
136
|
# address which is not trusted is the originating IP.
|
137
|
-
|
138
137
|
def remote_ip
|
139
|
-
|
140
|
-
|
138
|
+
remote_addr_list = @env['REMOTE_ADDR'] && @env['REMOTE_ADDR'].split(',').collect(&:strip)
|
139
|
+
|
140
|
+
unless remote_addr_list.blank?
|
141
|
+
not_trusted_addrs = remote_addr_list.reject {|addr| addr =~ TRUSTED_PROXIES}
|
142
|
+
return not_trusted_addrs.first unless not_trusted_addrs.empty?
|
141
143
|
end
|
144
|
+
remote_ips = @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_X_FORWARDED_FOR'].split(',')
|
142
145
|
|
143
146
|
if @env.include? 'HTTP_CLIENT_IP'
|
144
|
-
if
|
147
|
+
if remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP'])
|
145
148
|
# We don't know which came from the proxy, and which from the user
|
146
149
|
raise ActionControllerError.new(<<EOM)
|
147
150
|
IP spoofing attack?!
|
@@ -149,11 +152,11 @@ HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}
|
|
149
152
|
HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}
|
150
153
|
EOM
|
151
154
|
end
|
155
|
+
|
152
156
|
return @env['HTTP_CLIENT_IP']
|
153
157
|
end
|
154
158
|
|
155
|
-
if
|
156
|
-
remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',')
|
159
|
+
if remote_ips
|
157
160
|
while remote_ips.size > 1 && TRUSTED_PROXIES =~ remote_ips.last.strip
|
158
161
|
remote_ips.pop
|
159
162
|
end
|
File without changes
|
File without changes
|
@@ -88,6 +88,10 @@ module ActionController
|
|
88
88
|
#
|
89
89
|
# map.connect ':controller/:action/:id', :action => 'show', :defaults => { :page => 'Dashboard' }
|
90
90
|
#
|
91
|
+
# Note: The default routes, as provided by the Rails generator, make all actions in every
|
92
|
+
# controller accessible via GET requests. You should consider removing them or commenting
|
93
|
+
# them out if you're using named routes and resources.
|
94
|
+
#
|
91
95
|
# == Named routes
|
92
96
|
#
|
93
97
|
# Routes can be named with the syntax <tt>map.name_of_route options</tt>,
|
@@ -369,7 +373,7 @@ module ActionController
|
|
369
373
|
|
370
374
|
Routes = RouteSet.new
|
371
375
|
|
372
|
-
::Inflector.module_eval do
|
376
|
+
ActiveSupport::Inflector.module_eval do
|
373
377
|
# Ensures that routes are reloaded when Rails inflections are updated.
|
374
378
|
def inflections_with_route_reloading(&block)
|
375
379
|
returning(inflections_without_route_reloading(&block)) {
|
@@ -67,10 +67,9 @@ module ActionController
|
|
67
67
|
options = options.dup
|
68
68
|
|
69
69
|
if options[:namespace]
|
70
|
-
options[:controller] = "#{options
|
70
|
+
options[:controller] = "#{options.delete(:namespace).sub(/\/$/, '')}/#{options[:controller]}"
|
71
71
|
options.delete(:path_prefix)
|
72
72
|
options.delete(:name_prefix)
|
73
|
-
options.delete(:namespace)
|
74
73
|
end
|
75
74
|
|
76
75
|
requirements = (options.delete(:requirements) || {}).dup
|
@@ -249,7 +249,7 @@ module ActionController
|
|
249
249
|
end
|
250
250
|
|
251
251
|
def extract_value
|
252
|
-
"#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| URI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
|
252
|
+
"#{local_name} = hash[:#{key}] && Array(hash[:#{key}]).collect { |path_component| URI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
|
253
253
|
end
|
254
254
|
|
255
255
|
def default
|
@@ -171,7 +171,7 @@ module ActionController #:nodoc:
|
|
171
171
|
|
172
172
|
# Was the response successful?
|
173
173
|
def success?
|
174
|
-
response_code
|
174
|
+
(200..299).include?(response_code)
|
175
175
|
end
|
176
176
|
|
177
177
|
# Was the URL not found?
|
@@ -333,7 +333,7 @@ module ActionController #:nodoc:
|
|
333
333
|
attr_reader :original_filename
|
334
334
|
|
335
335
|
# The content type of the "uploaded" file
|
336
|
-
|
336
|
+
attr_accessor :content_type
|
337
337
|
|
338
338
|
def initialize(path, content_type = Mime::TEXT, binary = false)
|
339
339
|
raise "#{path} file does not exist" unless File.exist?(path)
|
@@ -413,6 +413,8 @@ module ActionController #:nodoc:
|
|
413
413
|
get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys)
|
414
414
|
end
|
415
415
|
|
416
|
+
deprecate :follow_redirect => "If you wish to follow redirects, you should use integration tests"
|
417
|
+
|
416
418
|
def assigns(key = nil)
|
417
419
|
if key.nil?
|
418
420
|
@response.template.assigns
|
@@ -17,7 +17,7 @@ module HTML #:nodoc:
|
|
17
17
|
@root = Node.new(nil)
|
18
18
|
node_stack = [ @root ]
|
19
19
|
while token = tokenizer.next
|
20
|
-
node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token)
|
20
|
+
node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token, strict)
|
21
21
|
|
22
22
|
node_stack.last.children << node unless node.tag? && node.closing == :close
|
23
23
|
if node.tag?
|
@@ -116,7 +116,7 @@ module ActionController #:nodoc:
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def apply_redirect_to(redirect_to_option) # :nodoc:
|
119
|
-
redirect_to_option.is_a?(Symbol) ? self.send!(redirect_to_option) : redirect_to_option
|
119
|
+
(redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.send!(redirect_to_option) : redirect_to_option
|
120
120
|
end
|
121
121
|
|
122
122
|
def apply_remaining_actions(options) # :nodoc:
|
data/lib/action_pack/version.rb
CHANGED
data/lib/action_view/base.rb
CHANGED
@@ -178,10 +178,13 @@ module ActionView #:nodoc:
|
|
178
178
|
# that alert()s the caught exception (and then re-raises it).
|
179
179
|
@@debug_rjs = false
|
180
180
|
cattr_accessor :debug_rjs
|
181
|
-
|
181
|
+
|
182
182
|
@@erb_variable = '_erbout'
|
183
183
|
cattr_accessor :erb_variable
|
184
|
-
|
184
|
+
class << self
|
185
|
+
deprecate :erb_variable= => 'The erb variable will no longer be configurable. Use the concat helper method instead of appending to it directly.'
|
186
|
+
end
|
187
|
+
|
185
188
|
attr_internal :request
|
186
189
|
|
187
190
|
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
|
@@ -253,6 +256,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
|
|
253
256
|
elsif options == :update
|
254
257
|
update_page(&block)
|
255
258
|
elsif options.is_a?(Hash)
|
259
|
+
use_full_path = options[:use_full_path]
|
256
260
|
options = options.reverse_merge(:locals => {}, :use_full_path => true)
|
257
261
|
|
258
262
|
if partial_layout = options.delete(:layout)
|
@@ -266,7 +270,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
|
|
266
270
|
end
|
267
271
|
end
|
268
272
|
elsif options[:file]
|
269
|
-
render_file(options[:file],
|
273
|
+
render_file(options[:file], use_full_path || false, options[:locals])
|
270
274
|
elsif options[:partial] && options[:collection]
|
271
275
|
render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals])
|
272
276
|
elsif options[:partial]
|
@@ -485,21 +485,24 @@ module ActionView
|
|
485
485
|
source = "#{@controller.request.relative_url_root}#{source}"
|
486
486
|
end
|
487
487
|
end
|
488
|
-
source = rewrite_asset_path(source)
|
489
488
|
|
490
|
-
|
491
|
-
|
489
|
+
rewrite_asset_path(source)
|
490
|
+
end
|
491
|
+
end
|
492
492
|
|
493
|
-
|
494
|
-
host = "#{@controller.request.protocol}#{host}"
|
495
|
-
end
|
493
|
+
source = ActionView::Base.computed_public_paths[cache_key]
|
496
494
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
495
|
+
if include_host && source !~ %r{^[-a-z]+://}
|
496
|
+
host = compute_asset_host(source)
|
497
|
+
|
498
|
+
if has_request && !host.blank? && host !~ %r{^[-a-z]+://}
|
499
|
+
host = "#{@controller.request.protocol}#{host}"
|
502
500
|
end
|
501
|
+
|
502
|
+
"#{host}#{source}"
|
503
|
+
else
|
504
|
+
source
|
505
|
+
end
|
503
506
|
end
|
504
507
|
|
505
508
|
# Pick an asset host for this source. Returns +nil+ if no host is set,
|
@@ -696,15 +696,15 @@ module ActionView
|
|
696
696
|
|
697
697
|
class FormBuilder
|
698
698
|
def date_select(method, options = {}, html_options = {})
|
699
|
-
@template.date_select(@object_name, method, options.merge(:object => @object))
|
699
|
+
@template.date_select(@object_name, method, options.merge(:object => @object), html_options)
|
700
700
|
end
|
701
701
|
|
702
702
|
def time_select(method, options = {}, html_options = {})
|
703
|
-
@template.time_select(@object_name, method, options.merge(:object => @object))
|
703
|
+
@template.time_select(@object_name, method, options.merge(:object => @object), html_options)
|
704
704
|
end
|
705
705
|
|
706
706
|
def datetime_select(method, options = {}, html_options = {})
|
707
|
-
@template.datetime_select(@object_name, method, options.merge(:object => @object))
|
707
|
+
@template.datetime_select(@object_name, method, options.merge(:object => @object), html_options)
|
708
708
|
end
|
709
709
|
end
|
710
710
|
end
|
@@ -601,7 +601,11 @@ module ActionView
|
|
601
601
|
end
|
602
602
|
|
603
603
|
def object
|
604
|
-
@object ||
|
604
|
+
@object || @template_object.instance_variable_get("@#{@object_name}")
|
605
|
+
rescue NameError
|
606
|
+
# As @object_name may contain the nested syntax (item[subobject]) we
|
607
|
+
# need to fallback to nil.
|
608
|
+
nil
|
605
609
|
end
|
606
610
|
|
607
611
|
def value(object)
|
@@ -304,7 +304,7 @@ module ActionView
|
|
304
304
|
#
|
305
305
|
# NOTE: Only the option tags are returned, you have to wrap this call in
|
306
306
|
# a regular HTML select tag.
|
307
|
-
def time_zone_options_for_select(selected = nil, priority_zones = nil, model = TimeZone)
|
307
|
+
def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
|
308
308
|
zone_options = ""
|
309
309
|
|
310
310
|
zones = model.all
|
@@ -417,7 +417,7 @@ module ActionView
|
|
417
417
|
value = value(object)
|
418
418
|
content_tag("select",
|
419
419
|
add_options(
|
420
|
-
time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || TimeZone),
|
420
|
+
time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || ActiveSupport::TimeZone),
|
421
421
|
options, value
|
422
422
|
), html_options
|
423
423
|
)
|
@@ -129,7 +129,7 @@ module ActionView
|
|
129
129
|
# label_tag 'name', nil, :class => 'small_label'
|
130
130
|
# # => <label for="name" class="small_label">Name</label>
|
131
131
|
def label_tag(name, text = nil, options = {})
|
132
|
-
content_tag :label, text || name.humanize, { "for" => name }.update(options.stringify_keys)
|
132
|
+
content_tag :label, text || name.to_s.humanize, { "for" => name }.update(options.stringify_keys)
|
133
133
|
end
|
134
134
|
|
135
135
|
# Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or
|
@@ -348,11 +348,13 @@ module ActionView
|
|
348
348
|
options.stringify_keys!
|
349
349
|
|
350
350
|
if disable_with = options.delete("disable_with")
|
351
|
+
disable_with = "this.value='#{disable_with}'"
|
352
|
+
disable_with << ";#{options.delete('onclick')}" if options['onclick']
|
353
|
+
|
351
354
|
options["onclick"] = [
|
352
355
|
"this.setAttribute('originalValue', this.value)",
|
353
356
|
"this.disabled=true",
|
354
|
-
|
355
|
-
"#{options["onclick"]}",
|
357
|
+
disable_with,
|
356
358
|
"result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit())",
|
357
359
|
"if (result == false) { this.value = this.getAttribute('originalValue'); this.disabled = false }",
|
358
360
|
"return result;",
|