actionpack 1.9.0 → 1.9.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 +38 -0
- data/README +1 -1
- data/lib/action_controller/auto_complete.rb +2 -2
- data/lib/action_controller/base.rb +21 -13
- data/lib/action_controller/cgi_process.rb +16 -23
- data/lib/action_controller/routing.rb +17 -9
- data/lib/action_controller/session/active_record_store.rb +4 -4
- data/lib/action_controller/test_process.rb +37 -1
- data/lib/action_view.rb +2 -8
- data/lib/action_view/helpers/javascript_helper.rb +20 -12
- data/lib/action_view/helpers/javascripts/controls.js +254 -69
- data/lib/action_view/helpers/javascripts/dragdrop.js +131 -70
- data/lib/action_view/helpers/javascripts/effects.js +140 -98
- data/lib/action_view/helpers/javascripts/prototype.js +50 -39
- data/lib/action_view/helpers/tag_helper.rb +3 -2
- data/lib/action_view/helpers/text_helper.rb +1 -1
- data/lib/action_view/helpers/url_helper.rb +1 -1
- data/rakefile +2 -2
- data/test/controller/active_record_store_test.rb +9 -3
- data/test/controller/filters_test.rb +21 -0
- data/test/controller/new_render_test.rb +27 -0
- data/test/controller/routing_test.rb +70 -1
- data/test/controller/test_test.rb +37 -3
- data/test/template/form_helper_test.rb +3 -3
- data/test/template/form_tag_helper_test.rb +2 -2
- data/test/template/{javascript_helper.rb → javascript_helper_test.rb} +24 -20
- data/test/template/tag_helper_test.rb +8 -0
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
+
*1.9.1* (11 July, 2005)
|
2
|
+
|
3
|
+
* Fixed that auto_complete_for didn't force the input string to lower case even as the db comparison was
|
4
|
+
|
5
|
+
* Fixed that Action View should always use the included Builder, never attempt to require the gem, to ensure compatibility
|
6
|
+
|
7
|
+
* Added that nil options are not included in tags, so tag("p", :ignore => nil) now returns <p /> not <p ignore="" /> but that tag("p", :ignore => "") still includes it #1465 [michael@schuerig.de]
|
8
|
+
|
9
|
+
* Fixed that UrlHelper#link_to_unless/link_to_if used html_escape on the name if no link was to be applied. This is unnecessary and breaks its use with images #1649 [joergd@pobox.com]
|
10
|
+
|
11
|
+
* Improved error message for DoubleRenderError
|
12
|
+
|
13
|
+
* Fixed routing to allow for testing of *path components #1650 [Nicholas Seckar]
|
14
|
+
|
15
|
+
* Added :handle as an option to sortable_element to restrict the drag handle to a given class #1642 [thejohnny]
|
16
|
+
|
17
|
+
* Added a bunch of script.aculo.us features #1644, #1677, #1695 [Thomas Fuchs]
|
18
|
+
* Effect.ScrollTo, to smoothly scroll the page to an element
|
19
|
+
* Better Firefox flickering handling on SlideUp/SlideDown
|
20
|
+
* Removed a possible memory leak in IE with draggables
|
21
|
+
* Added support for cancelling dragging my hitting ESC
|
22
|
+
* Added capability to remove draggables/droppables and redeclare sortables in dragdrop.js (this makes it possible to call sortable_element on the same element more than once, e.g. in AJAX returns that modify the sortable element. all current sortable 'stuff' on the element will be discarded and the sortable will be rebuilt)
|
23
|
+
* Always reset background color on Effect.Highlight; this make change backwards-compatibility, to be sure include style="background-color:(target-color)" on your elements or else elements will fall back to their CSS rules (which is a good thing in most circumstances)
|
24
|
+
* Removed circular references from element to prevent memory leaks (still not completely gone in IE)
|
25
|
+
* Changes to class extension in effects.js
|
26
|
+
* Make Effect.Highlight restore any previously set background color when finishing (makes effect work with CSS classes that set a background color)
|
27
|
+
* Fixed myriads of memory leaks in IE and Gecko-based browsers [David Zülke]
|
28
|
+
* Added incremental and local autocompleting and loads of documentation to controls.js [Ivan Krstic]
|
29
|
+
* Extended the auto_complete_field helper to accept tokens option
|
30
|
+
* Changed object extension mechanism to favor Object.extend to make script.aculo.us easily adaptable to support 3rd party libs like IE7.js [David Zülke]
|
31
|
+
|
32
|
+
* Fixed that named routes didn't use the default values for action and possible other parameters #1534 [Nicholas Seckar]
|
33
|
+
|
34
|
+
* Fixed JavascriptHelper#visual_effect to use camelize such that :blind_up will work #1639 [pelletierm@eastmedia.net]
|
35
|
+
|
36
|
+
* Fixed that a SessionRestoreError was thrown if a model object was placed in the session that wasn't available to all controllers. This means that it's no longer necessary to use the 'model :post' work-around in ApplicationController to have a Post model in your session.
|
37
|
+
|
38
|
+
|
1
39
|
*1.9.0* (6 July, 2005)
|
2
40
|
|
3
41
|
* Added logging of the request URI in the benchmark statement (makes it easy to grep for slow actions)
|
data/README
CHANGED
@@ -174,7 +174,7 @@ A short rundown of the major features:
|
|
174
174
|
link_to_remote "Delete this post", :update => "posts",
|
175
175
|
:url => { :action => "destroy", :id => post.id }
|
176
176
|
|
177
|
-
{Learn more}[link:classes/ActionView/Helpers/
|
177
|
+
{Learn more}[link:classes/ActionView/Helpers/JavaScriptHelper.html]
|
178
178
|
|
179
179
|
|
180
180
|
* Pagination for navigating lists of results.
|
@@ -24,7 +24,7 @@ module ActionController
|
|
24
24
|
# auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC'
|
25
25
|
#
|
26
26
|
# For help on defining text input fields with autocompletion,
|
27
|
-
# see ActionView::Helpers::
|
27
|
+
# see ActionView::Helpers::JavaScriptHelper.
|
28
28
|
#
|
29
29
|
# For more examples, see script.aculo.us:
|
30
30
|
# * http://script.aculo.us/demos/ajax/autocompleter
|
@@ -33,7 +33,7 @@ module ActionController
|
|
33
33
|
def auto_complete_for(object, method, options = {})
|
34
34
|
define_method("auto_complete_for_#{object}_#{method}") do
|
35
35
|
find_options = {
|
36
|
-
:conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method] + '%' ],
|
36
|
+
:conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ],
|
37
37
|
:order => "#{method} ASC",
|
38
38
|
:limit => 10 }.merge!(options)
|
39
39
|
|
@@ -26,6 +26,11 @@ module ActionController #:nodoc:
|
|
26
26
|
class MissingFile < ActionControllerError #:nodoc:
|
27
27
|
end
|
28
28
|
class DoubleRenderError < ActionControllerError #:nodoc:
|
29
|
+
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\". Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so \"render(...) and return false\"."
|
30
|
+
|
31
|
+
def initialize(message=nil)
|
32
|
+
super(message || DEFAULT_MESSAGE)
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
# Action Controllers are made up of one or more actions that performs its purpose and then either renders a template or
|
@@ -179,16 +184,19 @@ module ActionController #:nodoc:
|
|
179
184
|
#
|
180
185
|
# == Calling multiple redirects or renders
|
181
186
|
#
|
182
|
-
#
|
187
|
+
# An action should conclude by a single render or redirect. Attempting to try to do either again will result in a DoubleRenderError:
|
183
188
|
#
|
184
189
|
# def do_something
|
185
190
|
# redirect_to :action => "elsewhere"
|
186
|
-
# render :action => "overthere"
|
191
|
+
# render :action => "overthere" # raises DoubleRenderError
|
187
192
|
# end
|
188
193
|
#
|
189
|
-
#
|
194
|
+
# If you need to redirect on the condition of something, then be sure to add "and return" to halt execution.
|
190
195
|
#
|
191
|
-
#
|
196
|
+
# def do_something
|
197
|
+
# redirect_to(:action => "elsewhere") and return if monkeys.nil?
|
198
|
+
# render :action => "overthere" # won't be called unless monkeys is nil
|
199
|
+
# end # == Environments
|
192
200
|
#
|
193
201
|
# Action Controller works out of the box with CGI, FastCGI, and mod_ruby. CGI and mod_ruby controllers are triggered just the same using:
|
194
202
|
#
|
@@ -455,9 +463,6 @@ module ActionController #:nodoc:
|
|
455
463
|
# # Renders the template for the action "goal" within the current controller
|
456
464
|
# render :action => "goal"
|
457
465
|
#
|
458
|
-
# # Renders the template for the action "explosion" from the ErrorsController
|
459
|
-
# render :action => "errors/explosion", :status => 500
|
460
|
-
#
|
461
466
|
# # Renders the template for the action "short_goal" within the current controller,
|
462
467
|
# # but without the current active layout
|
463
468
|
# render :action => "short_goal", :layout => false
|
@@ -500,14 +505,17 @@ module ActionController #:nodoc:
|
|
500
505
|
#
|
501
506
|
# === Rendering a file
|
502
507
|
#
|
503
|
-
# File rendering works just like action rendering except that it takes a
|
504
|
-
#
|
508
|
+
# File rendering works just like action rendering except that it takes a path relative to the template root or an absolute
|
509
|
+
# path if use_full_path is passed as true. The current layout is not applied automatically.
|
510
|
+
#
|
511
|
+
# # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.rhtml)
|
512
|
+
# render :file => "weblog/show"
|
505
513
|
#
|
506
514
|
# # Renders the template located in /path/to/some/template.r(html|xml)
|
507
|
-
# render :file => "/path/to/some/template"
|
515
|
+
# render :file => "/path/to/some/template", :use_full_path => false
|
508
516
|
#
|
509
517
|
# # Renders the same template within the current layout, but with a 404 status code
|
510
|
-
# render :file => "/path/to/some/template", :layout => true, :status => 404
|
518
|
+
# render :file => "/path/to/some/template", :use_full_path => false, :layout => true, :status => 404
|
511
519
|
#
|
512
520
|
# _Deprecation_ _notice_: This used to have the signature <tt>render_file(path, status = 200)</tt>
|
513
521
|
#
|
@@ -560,7 +568,7 @@ module ActionController #:nodoc:
|
|
560
568
|
# render :nothing => true, :status => 401
|
561
569
|
def render(options = {}, deprecated_status = nil) #:doc:
|
562
570
|
# puts "Rendering: #{options.inspect}"
|
563
|
-
raise DoubleRenderError
|
571
|
+
raise DoubleRenderError if performed?
|
564
572
|
|
565
573
|
# Backwards compatibility
|
566
574
|
return render({ :template => options || default_template_name, :status => deprecated_status }) if !options.is_a?(Hash)
|
@@ -684,7 +692,7 @@ module ActionController #:nodoc:
|
|
684
692
|
def redirect_to(options = {}, *parameters_for_method_reference) #:doc:
|
685
693
|
case options
|
686
694
|
when %r{^\w+://.*}
|
687
|
-
raise DoubleRenderError
|
695
|
+
raise DoubleRenderError if performed?
|
688
696
|
logger.info("Redirected to #{options}") unless logger.nil?
|
689
697
|
response.redirect(options)
|
690
698
|
response.redirected_to = options
|
@@ -95,29 +95,22 @@ module ActionController #:nodoc:
|
|
95
95
|
@session["__valid_session"]
|
96
96
|
return @session
|
97
97
|
rescue ArgumentError => e
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# end
|
115
|
-
raise(
|
116
|
-
ActionController::SessionRestoreError,
|
117
|
-
"Session contained objects where the class definition wasn't available. " +
|
118
|
-
"Remember to require classes for all objects kept in the session. " +
|
119
|
-
"(Original exception: #{e.message} [#{e.class}])"
|
120
|
-
)
|
98
|
+
if e.message =~ %r{undefined class/module (\w+)}
|
99
|
+
begin
|
100
|
+
Module.const_missing($1)
|
101
|
+
rescue LoadError, NameError => e
|
102
|
+
raise(
|
103
|
+
ActionController::SessionRestoreError,
|
104
|
+
"Session contained objects where the class definition wasn't available. " +
|
105
|
+
"Remember to require classes for all objects kept in the session. " +
|
106
|
+
"(Original exception: #{e.message} [#{e.class}])"
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
retry
|
111
|
+
else
|
112
|
+
raise
|
113
|
+
end
|
121
114
|
end
|
122
115
|
end
|
123
116
|
|
@@ -92,14 +92,14 @@ module ActionController
|
|
92
92
|
|
93
93
|
def initialize(key, options = {})
|
94
94
|
@key = key.to_sym
|
95
|
-
|
96
|
-
|
95
|
+
default, @condition = options[:default], options[:condition]
|
96
|
+
self.default = default if options.key?(:default)
|
97
97
|
end
|
98
98
|
|
99
99
|
def default_check(g)
|
100
100
|
presence = "#{g.hash_value(key, !! default)}"
|
101
101
|
if default
|
102
|
-
"!(#{presence} && #{g.hash_value(key, false)} != #{default.inspect})"
|
102
|
+
"!(#{presence} && #{g.hash_value(key, false)} != #{default.to_s.inspect})"
|
103
103
|
else
|
104
104
|
"! #{presence}"
|
105
105
|
end
|
@@ -210,7 +210,7 @@ module ActionController
|
|
210
210
|
mod_name = controller_name = segment = nil
|
211
211
|
|
212
212
|
while index < length
|
213
|
-
return nil unless /^[
|
213
|
+
return nil unless /^[A-Za-z][A-Za-z\d_]*$/ =~ (segment = segments[index])
|
214
214
|
index += 1
|
215
215
|
|
216
216
|
mod_name = segment.camelize
|
@@ -226,8 +226,12 @@ module ActionController
|
|
226
226
|
|
227
227
|
class PathComponent < DynamicComponent #:nodoc:
|
228
228
|
def optional?() true end
|
229
|
-
def default()
|
229
|
+
def default() [] end
|
230
230
|
def condition() nil end
|
231
|
+
|
232
|
+
def default=(value)
|
233
|
+
raise RoutingError, "All path components have an implicit default of []" unless value == []
|
234
|
+
end
|
231
235
|
|
232
236
|
def write_generation(g)
|
233
237
|
raise RoutingError, 'Path components must occur last' unless g.after.empty?
|
@@ -245,24 +249,28 @@ module ActionController
|
|
245
249
|
start = "(#{start})" unless /^\w+$/ =~ start
|
246
250
|
|
247
251
|
value_expr = "#{g.path_name}[#{start}..-1] || []"
|
248
|
-
g.result key, "ActionController::Routing::PathComponent::Result.
|
252
|
+
g.result key, "ActionController::Routing::PathComponent::Result.new_escaped(#{value_expr})"
|
249
253
|
g.finish(false)
|
250
254
|
end
|
251
255
|
|
252
256
|
class Result < ::Array
|
253
257
|
def to_s() join '/' end
|
258
|
+
def self.new_escaped(strings)
|
259
|
+
new strings.collect {|str| CGI.unescape str}
|
260
|
+
end
|
254
261
|
end
|
255
262
|
end
|
256
263
|
|
257
264
|
class Route #:nodoc:
|
258
265
|
attr_accessor :components, :known
|
259
|
-
attr_reader :path, :options, :keys
|
266
|
+
attr_reader :path, :options, :keys, :defaults
|
260
267
|
|
261
268
|
def initialize(path, options = {})
|
262
269
|
@path, @options = path, options
|
263
270
|
|
264
271
|
initialize_components path
|
265
272
|
defaults, conditions = initialize_hashes options.dup
|
273
|
+
@defaults = defaults.dup
|
266
274
|
configure_components(defaults, conditions)
|
267
275
|
initialize_keys
|
268
276
|
end
|
@@ -423,7 +431,7 @@ module ActionController
|
|
423
431
|
path.shift
|
424
432
|
|
425
433
|
hash = recognize_path(path)
|
426
|
-
recognition_failed(request) unless hash && hash['controller']
|
434
|
+
return recognition_failed(request) unless hash && hash['controller']
|
427
435
|
|
428
436
|
controller = hash['controller']
|
429
437
|
hash['controller'] = controller.controller_path
|
@@ -576,7 +584,7 @@ module ActionController
|
|
576
584
|
end
|
577
585
|
|
578
586
|
def name_route(route, name)
|
579
|
-
hash = route.known.symbolize_keys
|
587
|
+
hash = route.defaults.merge(route.known).symbolize_keys
|
580
588
|
hash[:controller] = "/#{hash[:controller]}"
|
581
589
|
|
582
590
|
define_method(hash_access_name(name)) { hash }
|
@@ -27,7 +27,7 @@ class CGI
|
|
27
27
|
# initialize(hash_of_session_id_and_data)
|
28
28
|
# attr_reader :session_id
|
29
29
|
# attr_accessor :data
|
30
|
-
# save
|
30
|
+
# save
|
31
31
|
# destroy
|
32
32
|
#
|
33
33
|
# The fast SqlBypass class is a generic SQL session store. You may
|
@@ -198,7 +198,7 @@ class CGI
|
|
198
198
|
@data
|
199
199
|
end
|
200
200
|
|
201
|
-
def save
|
201
|
+
def save
|
202
202
|
marshaled_data = self.class.marshal(data)
|
203
203
|
if @new_record
|
204
204
|
@new_record = false
|
@@ -240,7 +240,7 @@ class CGI
|
|
240
240
|
# Find or instantiate a session given a CGI::Session.
|
241
241
|
def initialize(session, option = nil)
|
242
242
|
session_id = session.session_id
|
243
|
-
unless @session = @@session_class.find_by_session_id(session_id)
|
243
|
+
unless @session = ActiveRecord::Base.silence { @@session_class.find_by_session_id(session_id) }
|
244
244
|
unless session.new_session
|
245
245
|
raise CGI::Session::NoSession, 'uninitialized session'
|
246
246
|
end
|
@@ -258,7 +258,7 @@ class CGI
|
|
258
258
|
# Save session store.
|
259
259
|
def update
|
260
260
|
if @session
|
261
|
-
ActiveRecord::Base.silence { @session.save
|
261
|
+
ActiveRecord::Base.silence { @session.save }
|
262
262
|
end
|
263
263
|
end
|
264
264
|
|
@@ -72,10 +72,16 @@ module ActionController #:nodoc:
|
|
72
72
|
extra_keys = ActionController::Routing::Routes.extra_keys(parameters)
|
73
73
|
non_path_parameters = get? ? query_parameters : request_parameters
|
74
74
|
parameters.each do |key, value|
|
75
|
+
if value.is_a? Fixnum
|
76
|
+
value = value.to_s
|
77
|
+
elsif value.is_a? Array
|
78
|
+
value = ActionController::Routing::PathComponent::Result.new(value)
|
79
|
+
end
|
80
|
+
|
75
81
|
if extra_keys.include?(key.to_sym)
|
76
82
|
non_path_parameters[key] = value
|
77
83
|
else
|
78
|
-
path_parameters[key] = value
|
84
|
+
path_parameters[key.to_s] = value
|
79
85
|
end
|
80
86
|
end
|
81
87
|
end
|
@@ -352,6 +358,36 @@ module Test
|
|
352
358
|
return @controller.send(selector, *args) if ActionController::Routing::NamedRoutes::Helpers.include?(selector)
|
353
359
|
return super
|
354
360
|
end
|
361
|
+
|
362
|
+
# A helper to make it easier to test different route configurations.
|
363
|
+
# This method temporarily replaces ActionController::Routing::Routes
|
364
|
+
# with a new RouteSet instance.
|
365
|
+
#
|
366
|
+
# The new instance is yielded to the passed block. Typically the block
|
367
|
+
# will create some routes using map.draw { map.connect ... }:
|
368
|
+
#
|
369
|
+
# with_routing do |set|
|
370
|
+
# set.draw { set.connect ':controller/:id/:action' }
|
371
|
+
# assert_equal(
|
372
|
+
# ['/content/10/show', {}],
|
373
|
+
# set.generate(:controller => 'content', :id => 10, :action => 'show')
|
374
|
+
# )
|
375
|
+
# end
|
376
|
+
#
|
377
|
+
def with_routing
|
378
|
+
real_routes = ActionController::Routing::Routes
|
379
|
+
ActionController::Routing.send :remove_const, :Routes
|
380
|
+
|
381
|
+
temporary_routes = ActionController::Routing::RouteSet.new
|
382
|
+
ActionController::Routing.send :const_set, :Routes, temporary_routes
|
383
|
+
|
384
|
+
yield temporary_routes
|
385
|
+
ensure
|
386
|
+
if ActionController::Routing.const_defined? :Routes
|
387
|
+
ActionController::Routing.send(:remove_const, :Routes)
|
388
|
+
end
|
389
|
+
ActionController::Routing.const_set(:Routes, real_routes) if real_routes
|
390
|
+
end
|
355
391
|
end
|
356
392
|
end
|
357
393
|
end
|
data/lib/action_view.rb
CHANGED
@@ -21,14 +21,8 @@
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
require 'builder'
|
27
|
-
rescue LoadError
|
28
|
-
# RubyGems is not available, use included Builder
|
29
|
-
$:.unshift(File.dirname(__FILE__) + "/action_view/vendor")
|
30
|
-
require 'action_view/vendor/builder'
|
31
|
-
end
|
24
|
+
$:.unshift(File.dirname(__FILE__) + "/action_view/vendor")
|
25
|
+
require 'action_view/vendor/builder'
|
32
26
|
|
33
27
|
require 'action_view/base'
|
34
28
|
require 'action_view/partials'
|
@@ -72,7 +72,7 @@ module ActionView
|
|
72
72
|
# :url => { :action => "undo", :n => word_counter },
|
73
73
|
# :complete => "undoRequestCompleted(request)"
|
74
74
|
#
|
75
|
-
# The callbacks that may be specified are:
|
75
|
+
# The callbacks that may be specified are (in order):
|
76
76
|
#
|
77
77
|
# <tt>:loading</tt>:: Called when the remote document is being
|
78
78
|
# loaded with data by the browser.
|
@@ -81,13 +81,15 @@ module ActionView
|
|
81
81
|
# <tt>:interactive</tt>:: Called when the user can interact with the
|
82
82
|
# remote document, even though it has not
|
83
83
|
# finished loading.
|
84
|
-
# <tt>:
|
85
|
-
# and the HTTP status code is
|
86
|
-
# <tt>:failure</tt>:: Called when the XMLHttpRequest is
|
87
|
-
# and the HTTP status code is
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
84
|
+
# <tt>:success</tt>:: Called when the XMLHttpRequest is completed,
|
85
|
+
# and the HTTP status code is in the 2XX range.
|
86
|
+
# <tt>:failure</tt>:: Called when the XMLHttpRequest is completed,
|
87
|
+
# and the HTTP status code is not in the 2XX
|
88
|
+
# range.
|
89
|
+
# <tt>:complete</tt>:: Called when the XMLHttpRequest is complete
|
90
|
+
# (fires after success/failure if they are present).,
|
91
|
+
#
|
92
|
+
# You can further refine <tt>:success</tt> and <tt>:failure</tt> by adding additional
|
91
93
|
# callbacks for specific status codes:
|
92
94
|
#
|
93
95
|
# Example:
|
@@ -96,6 +98,7 @@ module ActionView
|
|
96
98
|
# 404 => "alert('Not found...? Wrong URL...?')",
|
97
99
|
# :failure => "alert('HTTP Error ' + request.status + '!')"
|
98
100
|
#
|
101
|
+
# A status code callback overrides the success/failure handlers if present.
|
99
102
|
#
|
100
103
|
# If you for some reason or another need synchronous processing (that'll
|
101
104
|
# block the browser while the request is happening), you can specify
|
@@ -358,8 +361,13 @@ module ActionView
|
|
358
361
|
function << "'#{field_id}', "
|
359
362
|
function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', "
|
360
363
|
function << "'#{url_for(options[:url])}'"
|
361
|
-
|
364
|
+
|
362
365
|
js_options = {}
|
366
|
+
if options[:tokens] and options[:tokens].kind_of?(Array)
|
367
|
+
js_options[:tokens] = "['#{options[:tokens].join('\',\'')}']"
|
368
|
+
elsif options[:tokens]
|
369
|
+
js_options[:tokens] = "'#{options[:tokens]}'" if options[:tokens]
|
370
|
+
end
|
363
371
|
js_options[:callback] = "function(element, value) { return #{options[:with]} }" if options[:with]
|
364
372
|
js_options[:indicator] = "'#{options[:indicator]}'" if options[:indicator]
|
365
373
|
function << (', ' + options_for_javascript(js_options) + ')')
|
@@ -419,7 +427,7 @@ module ActionView
|
|
419
427
|
# http://script.aculo.us for more documentation.
|
420
428
|
def visual_effect(name, element_id = false, js_options = {})
|
421
429
|
element = element_id ? "'#{element_id}'" : "element"
|
422
|
-
"new Effect.#{name.to_s.
|
430
|
+
"new Effect.#{name.to_s.camelize}(#{element},#{options_for_javascript(js_options)});"
|
423
431
|
end
|
424
432
|
|
425
433
|
# Makes the element with the DOM ID specified by +element_id+ sortable
|
@@ -441,7 +449,7 @@ module ActionView
|
|
441
449
|
options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
|
442
450
|
options.delete_if { |key, value| AJAX_OPTIONS.include?(key) }
|
443
451
|
|
444
|
-
[:tag, :overlap, :constraint].each do |option|
|
452
|
+
[:tag, :overlap, :constraint, :handle].each do |option|
|
445
453
|
options[option] = "'#{options[option]}'" if options[option]
|
446
454
|
end
|
447
455
|
|
@@ -504,7 +512,7 @@ module ActionView
|
|
504
512
|
|
505
513
|
private
|
506
514
|
def options_for_javascript(options)
|
507
|
-
'{' + options.map {|k, v| "#{k}:#{v}"}.join(', ') + '}'
|
515
|
+
'{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}'
|
508
516
|
end
|
509
517
|
|
510
518
|
def options_for_ajax(options)
|