actionpack 1.12.5 → 1.13.0
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 +517 -15
- data/MIT-LICENSE +1 -1
- data/README +18 -20
- data/Rakefile +7 -4
- data/examples/address_book_controller.rb +3 -3
- data/examples/blog_controller.cgi +3 -3
- data/examples/debate_controller.cgi +5 -5
- data/lib/action_controller.rb +2 -2
- data/lib/action_controller/assertions.rb +73 -311
- data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
- data/lib/action_controller/assertions/dom_assertions.rb +25 -0
- data/lib/action_controller/assertions/model_assertions.rb +12 -0
- data/lib/action_controller/assertions/response_assertions.rb +140 -0
- data/lib/action_controller/assertions/routing_assertions.rb +82 -0
- data/lib/action_controller/assertions/selector_assertions.rb +571 -0
- data/lib/action_controller/assertions/tag_assertions.rb +117 -0
- data/lib/action_controller/base.rb +334 -163
- data/lib/action_controller/benchmarking.rb +3 -6
- data/lib/action_controller/caching.rb +83 -22
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
- data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
- data/lib/action_controller/cgi_process.rb +50 -27
- data/lib/action_controller/components.rb +21 -25
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
- data/lib/action_controller/filters.rb +448 -225
- data/lib/action_controller/flash.rb +24 -20
- data/lib/action_controller/helpers.rb +2 -5
- data/lib/action_controller/integration.rb +40 -16
- data/lib/action_controller/layout.rb +11 -8
- data/lib/action_controller/macros/auto_complete.rb +3 -2
- data/lib/action_controller/macros/in_place_editing.rb +3 -2
- data/lib/action_controller/mime_responds.rb +41 -29
- data/lib/action_controller/mime_type.rb +68 -10
- data/lib/action_controller/pagination.rb +4 -3
- data/lib/action_controller/request.rb +22 -14
- data/lib/action_controller/rescue.rb +25 -22
- data/lib/action_controller/resources.rb +302 -0
- data/lib/action_controller/response.rb +20 -2
- data/lib/action_controller/response.rb.rej +17 -0
- data/lib/action_controller/routing.rb +1165 -567
- data/lib/action_controller/scaffolding.rb +30 -31
- data/lib/action_controller/session/active_record_store.rb +2 -0
- data/lib/action_controller/session/drb_store.rb +4 -0
- data/lib/action_controller/session/mem_cache_store.rb +4 -0
- data/lib/action_controller/session_management.rb +6 -9
- data/lib/action_controller/status_codes.rb +89 -0
- data/lib/action_controller/streaming.rb +6 -15
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
- data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
- data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +52 -30
- data/lib/action_controller/url_rewriter.rb +63 -29
- data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
- data/lib/action_controller/verification.rb +22 -11
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +46 -43
- data/lib/action_view/compiled_templates.rb +1 -1
- data/lib/action_view/helpers/active_record_helper.rb +54 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
- data/lib/action_view/helpers/capture_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +258 -136
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/deprecated_helper.rb +34 -0
- data/lib/action_view/helpers/form_helper.rb +75 -35
- data/lib/action_view/helpers/form_options_helper.rb +7 -5
- data/lib/action_view/helpers/form_tag_helper.rb +44 -6
- data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
- data/lib/action_view/helpers/javascript_helper.rb +71 -10
- data/lib/action_view/helpers/javascripts/controls.js +41 -23
- data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
- data/lib/action_view/helpers/javascripts/effects.js +293 -163
- data/lib/action_view/helpers/javascripts/prototype.js +897 -389
- data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
- data/lib/action_view/helpers/number_helper.rb +111 -65
- data/lib/action_view/helpers/prototype_helper.rb +84 -109
- data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
- data/lib/action_view/helpers/tag_helper.rb +69 -16
- data/lib/action_view/helpers/text_helper.rb +149 -112
- data/lib/action_view/helpers/url_helper.rb +200 -107
- data/lib/action_view/template_error.rb +66 -42
- data/test/abstract_unit.rb +4 -2
- data/test/active_record_unit.rb +84 -56
- data/test/activerecord/active_record_assertions_test.rb +26 -18
- data/test/activerecord/active_record_store_test.rb +4 -36
- data/test/activerecord/pagination_test.rb +1 -6
- data/test/controller/action_pack_assertions_test.rb +230 -113
- data/test/controller/addresses_render_test.rb +2 -6
- data/test/controller/assert_select_test.rb +576 -0
- data/test/controller/base_test.rb +73 -3
- data/test/controller/caching_test.rb +228 -0
- data/test/controller/capture_test.rb +12 -10
- data/test/controller/cgi_test.rb +89 -12
- data/test/controller/components_test.rb +24 -2
- data/test/controller/content_type_test.rb +139 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +33 -25
- data/test/controller/deprecated_instance_variables_test.rb +48 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
- data/test/controller/fake_controllers.rb +0 -1
- data/test/controller/filters_test.rb +301 -16
- data/test/controller/flash_test.rb +19 -2
- data/test/controller/helper_test.rb +2 -2
- data/test/controller/integration_test.rb +154 -0
- data/test/controller/layout_test.rb +115 -1
- data/test/controller/mime_responds_test.rb +94 -0
- data/test/controller/mime_type_test.rb +9 -0
- data/test/controller/new_render_test.rb +161 -11
- data/test/controller/raw_post_test.rb +52 -15
- data/test/controller/redirect_test.rb +27 -14
- data/test/controller/render_test.rb +76 -29
- data/test/controller/request_test.rb +55 -4
- data/test/controller/resources_test.rb +274 -0
- data/test/controller/routing_test.rb +1533 -824
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +9 -1
- data/test/controller/session_management_test.rb +51 -0
- data/test/controller/test_test.rb +113 -29
- data/test/controller/url_rewriter_test.rb +86 -17
- data/test/controller/verification_test.rb +19 -17
- data/test/controller/webservice_test.rb +0 -7
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/test/_hello.rxml +1 -0
- data/test/fixtures/test/hello_world_container.rxml +3 -0
- data/test/fixtures/topic.rb +2 -2
- data/test/template/active_record_helper_test.rb +83 -12
- data/test/template/asset_tag_helper_test.rb +75 -95
- data/test/template/compiled_templates_test.rb +1 -0
- data/test/template/date_helper_test.rb +873 -181
- data/test/template/deprecated_helper_test.rb +36 -0
- data/test/template/deprecated_instance_variables_test.rb +43 -0
- data/test/template/form_helper_test.rb +77 -1
- data/test/template/form_options_helper_test.rb +4 -0
- data/test/template/form_tag_helper_test.rb +66 -2
- data/test/template/java_script_macros_helper_test.rb +4 -1
- data/test/template/javascript_helper_test.rb +29 -0
- data/test/template/number_helper_test.rb +63 -27
- data/test/template/prototype_helper_test.rb +77 -34
- data/test/template/tag_helper_test.rb +34 -6
- data/test/template/text_helper_test.rb +69 -34
- data/test/template/url_helper_test.rb +168 -16
- data/test/testing_sandbox.rb +7 -22
- metadata +66 -20
- data/filler.txt +0 -50
- data/lib/action_controller/code_generation.rb +0 -235
- data/lib/action_controller/vendor/xml_simple.rb +0 -1019
- data/test/controller/caching_filestore.rb +0 -74
- data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
- data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
- data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
- data/test/fixtures/dont_load.rb +0 -3
@@ -1,43 +1,64 @@
|
|
1
1
|
module ActionView
|
2
|
-
module Helpers
|
3
|
-
# Provides methods for converting a
|
4
|
-
#
|
2
|
+
module Helpers #:nodoc:
|
3
|
+
# Provides methods for converting a numbers into formatted strings.
|
4
|
+
# Methods are provided for phone numbers, currency, percentage,
|
5
|
+
# precision, positional notation, and file size.
|
5
6
|
module NumberHelper
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
7
|
+
# Formats a +number+ into a US phone number. You can customize the format
|
8
|
+
# in the +options+ hash.
|
9
|
+
# * <tt>:area_code</tt> - Adds parentheses around the area code.
|
10
|
+
# * <tt>:delimiter</tt> - Specifies the delimiter to use, defaults to "-".
|
11
|
+
# * <tt>:extension</tt> - Specifies an extension to add to the end of the
|
12
|
+
# generated number
|
13
|
+
# * <tt>:country_code</tt> - Sets the country code for the phone number.
|
14
|
+
#
|
15
|
+
# number_to_phone(1235551234) => 123-555-1234
|
16
|
+
# number_to_phone(1235551234, :area_code => true) => (123) 555-1234
|
17
|
+
# number_to_phone(1235551234, :delimiter => " ") => 123 555 1234
|
18
|
+
# number_to_phone(1235551234, :area_code => true, :extension => 555) => (123) 555-1234 x 555
|
19
|
+
# number_to_phone(1235551234, :country_code => 1)
|
15
20
|
def number_to_phone(number, options = {})
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
number = number.to_s.strip unless number.nil?
|
22
|
+
options = options.stringify_keys
|
23
|
+
area_code = options["area_code"] || nil
|
24
|
+
delimiter = options["delimiter"] || "-"
|
25
|
+
extension = options["extension"].to_s.strip || nil
|
26
|
+
country_code = options["country_code"] || nil
|
27
|
+
|
20
28
|
begin
|
21
|
-
str =
|
22
|
-
|
29
|
+
str = ""
|
30
|
+
str << "+#{country_code}#{delimiter}" unless country_code.blank?
|
31
|
+
str << if area_code
|
32
|
+
number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{delimiter}\\3")
|
33
|
+
else
|
34
|
+
number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
|
35
|
+
end
|
36
|
+
str << " x #{extension}" unless extension.blank?
|
37
|
+
str
|
23
38
|
rescue
|
24
39
|
number
|
25
40
|
end
|
26
41
|
end
|
27
42
|
|
28
|
-
# Formats a +number+ into a currency string.
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
43
|
+
# Formats a +number+ into a currency string. You can customize the format
|
44
|
+
# in the +options+ hash.
|
45
|
+
# * <tt>:precision</tt> - Sets the level of precision, defaults to 2
|
46
|
+
# * <tt>:unit</tt> - Sets the denomination of the currency, defaults to "$"
|
47
|
+
# * <tt>:separator</tt> - Sets the separator between the units, defaults to "."
|
48
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter, defaults to ","
|
49
|
+
#
|
50
|
+
# number_to_currency(1234567890.50) => $1,234,567,890.50
|
51
|
+
# number_to_currency(1234567890.506) => $1,234,567,890.51
|
52
|
+
# number_to_currency(1234567890.506, :precision => 3) => $1,234,567,890.506
|
53
|
+
# number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "")
|
54
|
+
# => £1234567890,50
|
37
55
|
def number_to_currency(number, options = {})
|
38
|
-
options
|
39
|
-
precision
|
40
|
-
|
56
|
+
options = options.stringify_keys
|
57
|
+
precision = options["precision"] || 2
|
58
|
+
unit = options["unit"] || "$"
|
59
|
+
separator = precision > 0 ? options["separator"] || "." : ""
|
60
|
+
delimiter = options["delimiter"] || ","
|
61
|
+
|
41
62
|
begin
|
42
63
|
parts = number_with_precision(number, precision).split('.')
|
43
64
|
unit + number_with_delimiter(parts[0], delimiter) + separator + parts[1].to_s
|
@@ -46,16 +67,19 @@ module ActionView
|
|
46
67
|
end
|
47
68
|
end
|
48
69
|
|
49
|
-
# Formats a +number+ as
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
70
|
+
# Formats a +number+ as a percentage string. You can customize the
|
71
|
+
# format in the +options+ hash.
|
72
|
+
# * <tt>:precision</tt> - Sets the level of precision, defaults to 3
|
73
|
+
# * <tt>:separator</tt> - Sets the separator between the units, defaults to "."
|
74
|
+
#
|
75
|
+
# number_to_percentage(100) => 100.000%
|
76
|
+
# number_to_percentage(100, {:precision => 0}) => 100%
|
77
|
+
# number_to_percentage(302.0574, {:precision => 2}) => 302.06%
|
56
78
|
def number_to_percentage(number, options = {})
|
57
|
-
options
|
58
|
-
precision
|
79
|
+
options = options.stringify_keys
|
80
|
+
precision = options["precision"] || 3
|
81
|
+
separator = options["separator"] || "."
|
82
|
+
|
59
83
|
begin
|
60
84
|
number = number_with_precision(number, precision)
|
61
85
|
parts = number.split('.')
|
@@ -69,41 +93,63 @@ module ActionView
|
|
69
93
|
end
|
70
94
|
end
|
71
95
|
|
72
|
-
# Formats a +number+ with
|
73
|
-
#
|
74
|
-
#
|
75
|
-
|
76
|
-
|
96
|
+
# Formats a +number+ with grouped thousands using +delimiter+. You
|
97
|
+
# can customize the format in the +options+ hash.
|
98
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter, defaults to ","
|
99
|
+
# * <tt>:separator</tt> - Sets the separator between the units, defaults to "."
|
100
|
+
#
|
101
|
+
# number_with_delimiter(12345678) => 12,345,678
|
102
|
+
# number_with_delimiter(12345678.05) => 12,345,678.05
|
103
|
+
# number_with_delimiter(12345678, :delimiter => ".") => 12.345.678
|
104
|
+
def number_with_delimiter(number, delimiter=",", separator=".")
|
105
|
+
begin
|
106
|
+
parts = number.to_s.split(separator)
|
107
|
+
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
|
108
|
+
parts.join separator
|
109
|
+
rescue
|
110
|
+
number
|
111
|
+
end
|
77
112
|
end
|
78
|
-
|
79
|
-
#
|
113
|
+
|
114
|
+
# Formats a +number+ with the specified level of +precision+. The default
|
115
|
+
# level of precision is 3.
|
116
|
+
#
|
117
|
+
# number_with_precision(111.2345) => 111.235
|
118
|
+
# number_with_precision(111.2345, 2) => 111.24
|
119
|
+
def number_with_precision(number, precision=3)
|
120
|
+
"%01.#{precision}f" % number
|
121
|
+
rescue
|
122
|
+
number
|
123
|
+
end
|
124
|
+
|
125
|
+
# Formats the bytes in +size+ into a more understandable representation.
|
126
|
+
# Useful for reporting file sizes to users. This method returns nil if
|
127
|
+
# +size+ cannot be converted into a number. You can change the default
|
128
|
+
# precision of 1 in +precision+.
|
80
129
|
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
|
130
|
+
# number_to_human_size(123) => 123 Bytes
|
131
|
+
# number_to_human_size(1234) => 1.2 KB
|
132
|
+
# number_to_human_size(12345) => 12.1 KB
|
133
|
+
# number_to_human_size(1234567) => 1.2 MB
|
134
|
+
# number_to_human_size(1234567890) => 1.1 GB
|
135
|
+
# number_to_human_size(1234567890123) => 1.1 TB
|
136
|
+
# number_to_human_size(1234567, 2) => 1.18 MB
|
137
|
+
def number_to_human_size(size, precision=1)
|
138
|
+
size = Kernel.Float(size)
|
88
139
|
case
|
89
|
-
when size
|
90
|
-
when size < 1.
|
91
|
-
when size < 1.
|
92
|
-
when size < 1.
|
93
|
-
|
140
|
+
when size == 1 : "1 Byte"
|
141
|
+
when size < 1.kilobyte: "%d Bytes" % size
|
142
|
+
when size < 1.megabyte: "%.#{precision}f KB" % (size / 1.0.kilobyte)
|
143
|
+
when size < 1.gigabyte: "%.#{precision}f MB" % (size / 1.0.megabyte)
|
144
|
+
when size < 1.terabyte: "%.#{precision}f GB" % (size / 1.0.gigabyte)
|
145
|
+
else "%.#{precision}f TB" % (size / 1.0.terabyte)
|
94
146
|
end.sub('.0', '')
|
95
147
|
rescue
|
96
148
|
nil
|
97
149
|
end
|
98
150
|
|
99
151
|
alias_method :human_size, :number_to_human_size # deprecated alias
|
100
|
-
|
101
|
-
# Formats a +number+ with a level of +precision+.
|
102
|
-
# Example:
|
103
|
-
# number_with_precision(111.2345) => 111.235
|
104
|
-
def number_with_precision(number, precision=3)
|
105
|
-
sprintf("%01.#{precision}f", number)
|
106
|
-
end
|
152
|
+
deprecate :human_size => :number_to_human_size
|
107
153
|
end
|
108
154
|
end
|
109
155
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/javascript_helper'
|
2
1
|
require 'set'
|
3
2
|
|
4
3
|
module ActionView
|
@@ -39,7 +38,7 @@ module ActionView
|
|
39
38
|
# XMLHttpRequest. The result of that request can then be inserted into a
|
40
39
|
# DOM object whose id can be specified with <tt>options[:update]</tt>.
|
41
40
|
# Usually, the result would be a partial prepared by the controller with
|
42
|
-
#
|
41
|
+
# render :partial.
|
43
42
|
#
|
44
43
|
# Examples:
|
45
44
|
# link_to_remote "Delete this post", :update => "posts",
|
@@ -60,6 +59,12 @@ module ActionView
|
|
60
59
|
# influence how the target DOM element is updated. It must be one of
|
61
60
|
# <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.
|
62
61
|
#
|
62
|
+
# The method used is by default POST. You can also specify GET or you
|
63
|
+
# can simulate PUT or DELETE over POST. All specified with <tt>options[:method]</tt>
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
# link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
|
67
|
+
#
|
63
68
|
# By default, these remote requests are processed asynchronous during
|
64
69
|
# which various JavaScript callbacks can be triggered (for progress
|
65
70
|
# indicators and the likes). All callbacks get access to the
|
@@ -159,15 +164,20 @@ module ActionView
|
|
159
164
|
#
|
160
165
|
# By default the fall-through action is the same as the one specified in
|
161
166
|
# the :url (and the default method is :post).
|
162
|
-
|
167
|
+
#
|
168
|
+
# form_remote_tag also takes a block, like form_tag:
|
169
|
+
# <% form_remote_tag :url => '/posts' do -%>
|
170
|
+
# <div><%= submit_tag 'Save' %></div>
|
171
|
+
# <% end -%>
|
172
|
+
def form_remote_tag(options = {}, &block)
|
163
173
|
options[:form] = true
|
164
174
|
|
165
175
|
options[:html] ||= {}
|
166
|
-
options[:html][:onsubmit] =
|
167
|
-
|
168
|
-
|
176
|
+
options[:html][:onsubmit] =
|
177
|
+
(options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
|
178
|
+
"#{remote_function(options)}; return false;"
|
169
179
|
|
170
|
-
|
180
|
+
form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
|
171
181
|
end
|
172
182
|
|
173
183
|
# Works like form_remote_tag, but uses form_for semantics.
|
@@ -194,81 +204,6 @@ module ActionView
|
|
194
204
|
tag("input", options[:html], false)
|
195
205
|
end
|
196
206
|
|
197
|
-
# Returns a JavaScript function (or expression) that'll update a DOM
|
198
|
-
# element according to the options passed.
|
199
|
-
#
|
200
|
-
# * <tt>:content</tt>: The content to use for updating. Can be left out
|
201
|
-
# if using block, see example.
|
202
|
-
# * <tt>:action</tt>: Valid options are :update (assumed by default),
|
203
|
-
# :empty, :remove
|
204
|
-
# * <tt>:position</tt> If the :action is :update, you can optionally
|
205
|
-
# specify one of the following positions: :before, :top, :bottom,
|
206
|
-
# :after.
|
207
|
-
#
|
208
|
-
# Examples:
|
209
|
-
# <%= javascript_tag(update_element_function("products",
|
210
|
-
# :position => :bottom, :content => "<p>New product!</p>")) %>
|
211
|
-
#
|
212
|
-
# <% replacement_function = update_element_function("products") do %>
|
213
|
-
# <p>Product 1</p>
|
214
|
-
# <p>Product 2</p>
|
215
|
-
# <% end %>
|
216
|
-
# <%= javascript_tag(replacement_function) %>
|
217
|
-
#
|
218
|
-
# This method can also be used in combination with remote method call
|
219
|
-
# where the result is evaluated afterwards to cause multiple updates on
|
220
|
-
# a page. Example:
|
221
|
-
#
|
222
|
-
# # Calling view
|
223
|
-
# <%= form_remote_tag :url => { :action => "buy" },
|
224
|
-
# :complete => evaluate_remote_response %>
|
225
|
-
# all the inputs here...
|
226
|
-
#
|
227
|
-
# # Controller action
|
228
|
-
# def buy
|
229
|
-
# @product = Product.find(1)
|
230
|
-
# end
|
231
|
-
#
|
232
|
-
# # Returning view
|
233
|
-
# <%= update_element_function(
|
234
|
-
# "cart", :action => :update, :position => :bottom,
|
235
|
-
# :content => "<p>New Product: #{@product.name}</p>")) %>
|
236
|
-
# <% update_element_function("status", :binding => binding) do %>
|
237
|
-
# You've bought a new product!
|
238
|
-
# <% end %>
|
239
|
-
#
|
240
|
-
# Notice how the second call doesn't need to be in an ERb output block
|
241
|
-
# since it uses a block and passes in the binding to render directly.
|
242
|
-
# This trick will however only work in ERb (not Builder or other
|
243
|
-
# template forms).
|
244
|
-
#
|
245
|
-
# See also JavaScriptGenerator and update_page.
|
246
|
-
def update_element_function(element_id, options = {}, &block)
|
247
|
-
content = escape_javascript(options[:content] || '')
|
248
|
-
content = escape_javascript(capture(&block)) if block
|
249
|
-
|
250
|
-
javascript_function = case (options[:action] || :update)
|
251
|
-
when :update
|
252
|
-
if options[:position]
|
253
|
-
"new Insertion.#{options[:position].to_s.camelize}('#{element_id}','#{content}')"
|
254
|
-
else
|
255
|
-
"$('#{element_id}').innerHTML = '#{content}'"
|
256
|
-
end
|
257
|
-
|
258
|
-
when :empty
|
259
|
-
"$('#{element_id}').innerHTML = ''"
|
260
|
-
|
261
|
-
when :remove
|
262
|
-
"Element.remove('#{element_id}')"
|
263
|
-
|
264
|
-
else
|
265
|
-
raise ArgumentError, "Invalid action, choose one of :update, :remove, :empty"
|
266
|
-
end
|
267
|
-
|
268
|
-
javascript_function << ";\n"
|
269
|
-
options[:binding] ? concat(javascript_function, options[:binding]) : javascript_function
|
270
|
-
end
|
271
|
-
|
272
207
|
# Returns 'eval(request.responseText)' which is the JavaScript function
|
273
208
|
# that form_remote_tag can call in :complete to evaluate a multiple
|
274
209
|
# update return document using update_element_function calls.
|
@@ -289,7 +224,7 @@ module ActionView
|
|
289
224
|
javascript_options = options_for_ajax(options)
|
290
225
|
|
291
226
|
update = ''
|
292
|
-
if options[:update]
|
227
|
+
if options[:update] && options[:update].is_a?(Hash)
|
293
228
|
update = []
|
294
229
|
update << "success:'#{options[:update][:success]}'" if options[:update][:success]
|
295
230
|
update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure]
|
@@ -303,7 +238,7 @@ module ActionView
|
|
303
238
|
"new Ajax.Updater(#{update}, "
|
304
239
|
|
305
240
|
url_options = options[:url]
|
306
|
-
url_options = url_options.merge(:escape => false) if url_options.is_a?
|
241
|
+
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
|
307
242
|
function << "'#{url_for(url_options)}'"
|
308
243
|
function << ", #{javascript_options})"
|
309
244
|
|
@@ -438,7 +373,7 @@ module ActionView
|
|
438
373
|
if ActionView::Base.debug_rjs
|
439
374
|
source = javascript.dup
|
440
375
|
javascript.replace "try {\n#{source}\n} catch (e) "
|
441
|
-
javascript << "{ alert('RJS error:\\n\\n' + e.toString()); alert('#{source.gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }}'); throw e }"
|
376
|
+
javascript << "{ alert('RJS error:\\n\\n' + e.toString()); alert('#{source.gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }}'); throw e }"
|
442
377
|
end
|
443
378
|
end
|
444
379
|
end
|
@@ -453,6 +388,12 @@ module ActionView
|
|
453
388
|
JavaScriptElementProxy.new(self, id)
|
454
389
|
end
|
455
390
|
|
391
|
+
# Returns an object whose <tt>#to_json</tt> evaluates to +code+. Use this to pass a literal JavaScript
|
392
|
+
# expression as an argument to another JavaScriptGenerator method.
|
393
|
+
def literal(code)
|
394
|
+
ActiveSupport::JSON::Variable.new(code.to_s)
|
395
|
+
end
|
396
|
+
|
456
397
|
# Returns a collection reference by finding it through a CSS +pattern+ in the DOM. This collection can then be
|
457
398
|
# used for further method calls. Examples:
|
458
399
|
#
|
@@ -526,7 +467,7 @@ module ActionView
|
|
526
467
|
#
|
527
468
|
# # Replace the DOM element having ID 'person-45' with the
|
528
469
|
# # 'person' partial for the appropriate object.
|
529
|
-
#
|
470
|
+
# replace 'person-45', :partial => 'person', :object => @person
|
530
471
|
#
|
531
472
|
# This allows the same partial that is used for the +insert_html+ to
|
532
473
|
# be also used for the input to +replace+ without resorting to
|
@@ -550,22 +491,22 @@ module ActionView
|
|
550
491
|
|
551
492
|
# Removes the DOM elements with the given +ids+ from the page.
|
552
493
|
def remove(*ids)
|
553
|
-
|
494
|
+
loop_on_multiple_args 'Element.remove', ids
|
554
495
|
end
|
555
496
|
|
556
497
|
# Shows hidden DOM elements with the given +ids+.
|
557
498
|
def show(*ids)
|
558
|
-
|
499
|
+
loop_on_multiple_args 'Element.show', ids
|
559
500
|
end
|
560
501
|
|
561
502
|
# Hides the visible DOM elements with the given +ids+.
|
562
503
|
def hide(*ids)
|
563
|
-
|
504
|
+
loop_on_multiple_args 'Element.hide', ids
|
564
505
|
end
|
565
506
|
|
566
507
|
# Toggles the visibility of the DOM elements with the given +ids+.
|
567
508
|
def toggle(*ids)
|
568
|
-
|
509
|
+
loop_on_multiple_args 'Element.toggle', ids
|
569
510
|
end
|
570
511
|
|
571
512
|
# Displays an alert dialog with the given +message+.
|
@@ -573,16 +514,18 @@ module ActionView
|
|
573
514
|
call 'alert', message
|
574
515
|
end
|
575
516
|
|
576
|
-
# Redirects the browser to the given +location+, in the same form as
|
577
|
-
# +url_for+.
|
517
|
+
# Redirects the browser to the given +location+, in the same form as +url_for+.
|
578
518
|
def redirect_to(location)
|
579
519
|
assign 'window.location.href', @context.url_for(location)
|
580
520
|
end
|
581
521
|
|
582
|
-
# Calls the JavaScript +function+, optionally with the given
|
583
|
-
#
|
584
|
-
|
585
|
-
|
522
|
+
# Calls the JavaScript +function+, optionally with the given +arguments+.
|
523
|
+
#
|
524
|
+
# If a block is given, the block will be passed to a new JavaScriptGenerator;
|
525
|
+
# the resulting JavaScript code will then be wrapped inside <tt>function() { ... }</tt>
|
526
|
+
# and passed as the called function's final argument.
|
527
|
+
def call(function, *arguments, &block)
|
528
|
+
record "#{function}(#{arguments_for_call(arguments, block)})"
|
586
529
|
end
|
587
530
|
|
588
531
|
# Assigns the JavaScript +variable+ the given +value+.
|
@@ -633,12 +576,18 @@ module ActionView
|
|
633
576
|
end
|
634
577
|
|
635
578
|
private
|
579
|
+
def loop_on_multiple_args(method, ids)
|
580
|
+
record(ids.size>1 ?
|
581
|
+
"#{javascript_object_for(ids)}.each(#{method})" :
|
582
|
+
"#{method}(#{ids.first.to_json})")
|
583
|
+
end
|
584
|
+
|
636
585
|
def page
|
637
586
|
self
|
638
587
|
end
|
639
588
|
|
640
589
|
def record(line)
|
641
|
-
returning line = "#{line.to_s.chomp.gsub
|
590
|
+
returning line = "#{line.to_s.chomp.gsub(/\;\z/, '')};" do
|
642
591
|
self << line
|
643
592
|
end
|
644
593
|
end
|
@@ -653,10 +602,16 @@ module ActionView
|
|
653
602
|
object.respond_to?(:to_json) ? object.to_json : object.inspect
|
654
603
|
end
|
655
604
|
|
656
|
-
def arguments_for_call(arguments)
|
605
|
+
def arguments_for_call(arguments, block = nil)
|
606
|
+
arguments << block_to_function(block) if block
|
657
607
|
arguments.map { |argument| javascript_object_for(argument) }.join ', '
|
658
608
|
end
|
659
609
|
|
610
|
+
def block_to_function(block)
|
611
|
+
generator = self.class.new(@context, &block)
|
612
|
+
literal("function() { #{generator.to_s} }")
|
613
|
+
end
|
614
|
+
|
660
615
|
def method_missing(method, *arguments)
|
661
616
|
JavaScriptProxy.new(self, method.to_s.camelize)
|
662
617
|
end
|
@@ -673,8 +628,11 @@ module ActionView
|
|
673
628
|
# Works like update_page but wraps the generated JavaScript in a <script>
|
674
629
|
# tag. Use this to include generated JavaScript in an ERb template.
|
675
630
|
# See JavaScriptGenerator for more information.
|
676
|
-
|
677
|
-
|
631
|
+
#
|
632
|
+
# +html_options+ may be a hash of <script> attributes to be passed
|
633
|
+
# to ActionView::Helpers::JavaScriptHelper#javascript_tag.
|
634
|
+
def update_page_tag(html_options = {}, &block)
|
635
|
+
javascript_tag update_page(&block), html_options
|
678
636
|
end
|
679
637
|
|
680
638
|
protected
|
@@ -738,16 +696,16 @@ module ActionView
|
|
738
696
|
end
|
739
697
|
|
740
698
|
private
|
741
|
-
def method_missing(method, *arguments)
|
699
|
+
def method_missing(method, *arguments, &block)
|
742
700
|
if method.to_s =~ /(.*)=$/
|
743
701
|
assign($1, arguments.first)
|
744
702
|
else
|
745
|
-
call("#{method.to_s.camelize(:lower)}", *arguments)
|
703
|
+
call("#{method.to_s.camelize(:lower)}", *arguments, &block)
|
746
704
|
end
|
747
705
|
end
|
748
706
|
|
749
|
-
def call(function, *arguments)
|
750
|
-
append_to_function_chain!("#{function}(#{@generator.send(:arguments_for_call, arguments)})")
|
707
|
+
def call(function, *arguments, &block)
|
708
|
+
append_to_function_chain!("#{function}(#{@generator.send(:arguments_for_call, arguments, block)})")
|
751
709
|
self
|
752
710
|
end
|
753
711
|
|
@@ -756,7 +714,7 @@ module ActionView
|
|
756
714
|
end
|
757
715
|
|
758
716
|
def function_chain
|
759
|
-
@function_chain ||= @generator.instance_variable_get(
|
717
|
+
@function_chain ||= @generator.instance_variable_get(:@lines)
|
760
718
|
end
|
761
719
|
|
762
720
|
def append_to_function_chain!(call)
|
@@ -771,6 +729,21 @@ module ActionView
|
|
771
729
|
super(generator, "$(#{id.to_json})")
|
772
730
|
end
|
773
731
|
|
732
|
+
# Allows access of element attributes through +attribute+. Examples:
|
733
|
+
#
|
734
|
+
# page['foo']['style'] # => $('foo').style;
|
735
|
+
# page['foo']['style']['color'] # => $('blank_slate').style.color;
|
736
|
+
# page['foo']['style']['color'] = 'red' # => $('blank_slate').style.color = 'red';
|
737
|
+
# page['foo']['style'].color = 'red' # => $('blank_slate').style.color = 'red';
|
738
|
+
def [](attribute)
|
739
|
+
append_to_function_chain!(attribute)
|
740
|
+
self
|
741
|
+
end
|
742
|
+
|
743
|
+
def []=(variable, value)
|
744
|
+
assign(variable, value)
|
745
|
+
end
|
746
|
+
|
774
747
|
def replace_html(*options_for_render)
|
775
748
|
call 'update', @generator.send(:render, *options_for_render)
|
776
749
|
end
|
@@ -779,8 +752,8 @@ module ActionView
|
|
779
752
|
call 'replace', @generator.send(:render, *options_for_render)
|
780
753
|
end
|
781
754
|
|
782
|
-
def reload
|
783
|
-
replace :partial => @id.to_s
|
755
|
+
def reload(options_for_replace = {})
|
756
|
+
replace(options_for_replace.merge({ :partial => @id.to_s }))
|
784
757
|
end
|
785
758
|
|
786
759
|
end
|
@@ -811,8 +784,8 @@ module ActionView
|
|
811
784
|
end
|
812
785
|
|
813
786
|
class JavaScriptCollectionProxy < JavaScriptProxy #:nodoc:
|
814
|
-
ENUMERABLE_METHODS_WITH_RETURN = [:all, :any, :collect, :map, :detect, :find, :find_all, :select, :max, :min, :partition, :reject, :sort_by]
|
815
|
-
ENUMERABLE_METHODS = ENUMERABLE_METHODS_WITH_RETURN + [:each]
|
787
|
+
ENUMERABLE_METHODS_WITH_RETURN = [:all, :any, :collect, :map, :detect, :find, :find_all, :select, :max, :min, :partition, :reject, :sort_by] unless defined? ENUMERABLE_METHODS_WITH_RETURN
|
788
|
+
ENUMERABLE_METHODS = ENUMERABLE_METHODS_WITH_RETURN + [:each] unless defined? ENUMERABLE_METHODS
|
816
789
|
attr_reader :generator
|
817
790
|
delegate :arguments_for_call, :to => :generator
|
818
791
|
|
@@ -899,3 +872,5 @@ module ActionView
|
|
899
872
|
end
|
900
873
|
end
|
901
874
|
end
|
875
|
+
|
876
|
+
require File.dirname(__FILE__) + '/javascript_helper'
|