actionview 4.1.13 → 6.1.3.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +181 -359
- data/MIT-LICENSE +1 -1
- data/README.rdoc +12 -6
- data/lib/action_view/base.rb +115 -43
- data/lib/action_view/buffers.rb +22 -4
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +8 -12
- data/lib/action_view/dependency_tracker.rb +61 -21
- data/lib/action_view/digestor.rb +89 -84
- data/lib/action_view/flows.rb +12 -13
- data/lib/action_view/gem_version.rb +6 -4
- data/lib/action_view/helpers/active_model_helper.rb +16 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +311 -105
- data/lib/action_view/helpers/asset_url_helper.rb +197 -80
- data/lib/action_view/helpers/atom_feed_helper.rb +20 -17
- data/lib/action_view/helpers/cache_helper.rb +109 -45
- data/lib/action_view/helpers/capture_helper.rb +20 -22
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +8 -6
- data/lib/action_view/helpers/date_helper.rb +245 -140
- data/lib/action_view/helpers/debug_helper.rb +14 -17
- data/lib/action_view/helpers/form_helper.rb +875 -148
- data/lib/action_view/helpers/form_options_helper.rb +128 -82
- data/lib/action_view/helpers/form_tag_helper.rb +253 -91
- data/lib/action_view/helpers/javascript_helper.rb +37 -15
- data/lib/action_view/helpers/number_helper.rb +100 -77
- data/lib/action_view/helpers/output_safety_helper.rb +42 -10
- data/lib/action_view/helpers/rendering_helper.rb +26 -15
- data/lib/action_view/helpers/sanitize_helper.rb +79 -164
- data/lib/action_view/helpers/tag_helper.rb +277 -64
- data/lib/action_view/helpers/tags/base.rb +143 -92
- data/lib/action_view/helpers/tags/check_box.rb +20 -19
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -30
- data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +4 -3
- data/lib/action_view/helpers/tags/date_field.rb +3 -2
- data/lib/action_view/helpers/tags/date_select.rb +38 -37
- data/lib/action_view/helpers/tags/datetime_field.rb +14 -5
- data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +41 -22
- data/lib/action_view/helpers/tags/month_field.rb +3 -2
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +3 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
- data/lib/action_view/helpers/tags/radio_button.rb +7 -6
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +3 -0
- data/lib/action_view/helpers/tags/select.rb +11 -10
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +7 -1
- data/lib/action_view/helpers/tags/text_field.rb +11 -7
- data/lib/action_view/helpers/tags/time_field.rb +3 -2
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +39 -0
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +3 -2
- data/lib/action_view/helpers/tags.rb +4 -1
- data/lib/action_view/helpers/text_helper.rb +80 -45
- data/lib/action_view/helpers/translation_helper.rb +148 -67
- data/lib/action_view/helpers/url_helper.rb +289 -147
- data/lib/action_view/helpers.rb +5 -3
- data/lib/action_view/layouts.rb +68 -63
- data/lib/action_view/log_subscriber.rb +80 -13
- data/lib/action_view/lookup_context.rb +137 -92
- data/lib/action_view/model_naming.rb +4 -2
- data/lib/action_view/path_set.rb +30 -16
- data/lib/action_view/railtie.rb +62 -13
- data/lib/action_view/record_identifier.rb +53 -26
- data/lib/action_view/renderer/abstract_renderer.rb +152 -13
- data/lib/action_view/renderer/collection_renderer.rb +196 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
- data/lib/action_view/renderer/partial_renderer.rb +61 -261
- data/lib/action_view/renderer/renderer.rb +67 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +58 -54
- data/lib/action_view/renderer/template_renderer.rb +83 -75
- data/lib/action_view/rendering.rb +73 -46
- data/lib/action_view/routing_url_for.rb +54 -17
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +44 -29
- data/lib/action_view/template/handlers/builder.rb +12 -13
- data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
- data/lib/action_view/template/handlers/erb.rb +23 -89
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +4 -4
- data/lib/action_view/template/handlers.rb +22 -9
- data/lib/action_view/template/html.rb +10 -11
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +25 -0
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +267 -181
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +8 -10
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +109 -99
- data/lib/action_view/test_case.rb +73 -53
- data/lib/action_view/testing/resolvers.rb +24 -33
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +74 -44
- data/lib/action_view.rb +14 -9
- data/lib/assets/compiled/rails-ujs.js +746 -0
- metadata +71 -26
- data/lib/action_view/helpers/record_tag_helper.rb +0 -108
- data/lib/action_view/tasks/dependencies.rake +0 -23
- data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
- data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_view/vendor/html-scanner.rb +0 -20
@@ -1,11 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cgi"
|
4
|
+
require "action_view/helpers/tag_helper"
|
5
|
+
require "active_support/core_ext/string/output_safety"
|
6
|
+
require "active_support/core_ext/module/attribute_accessors"
|
7
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
5
8
|
|
6
9
|
module ActionView
|
7
10
|
# = Action View Form Tag Helpers
|
8
|
-
module Helpers
|
11
|
+
module Helpers #:nodoc:
|
9
12
|
# Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
|
10
13
|
# FormHelper does. Instead, you provide the names and values manually.
|
11
14
|
#
|
@@ -18,9 +21,11 @@ module ActionView
|
|
18
21
|
include TextHelper
|
19
22
|
|
20
23
|
mattr_accessor :embed_authenticity_token_in_remote_forms
|
21
|
-
self.embed_authenticity_token_in_remote_forms =
|
24
|
+
self.embed_authenticity_token_in_remote_forms = nil
|
25
|
+
|
26
|
+
mattr_accessor :default_enforce_utf8, default: true
|
22
27
|
|
23
|
-
# Starts a form tag that points the action to
|
28
|
+
# Starts a form tag that points the action to a URL configured with <tt>url_for_options</tt> just like
|
24
29
|
# ActionController::Base#url_for. The method for the form defaults to POST.
|
25
30
|
#
|
26
31
|
# ==== Options
|
@@ -67,7 +72,7 @@ module ActionView
|
|
67
72
|
def form_tag(url_for_options = {}, options = {}, &block)
|
68
73
|
html_options = html_options_for_form(url_for_options, options)
|
69
74
|
if block_given?
|
70
|
-
|
75
|
+
form_tag_with_body(html_options, capture(&block))
|
71
76
|
else
|
72
77
|
form_tag_html(html_options)
|
73
78
|
end
|
@@ -80,42 +85,48 @@ module ActionView
|
|
80
85
|
# associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
|
81
86
|
#
|
82
87
|
# ==== Options
|
83
|
-
# * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
|
88
|
+
# * <tt>:multiple</tt> - If set to true, the selection will allow multiple choices.
|
84
89
|
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
85
|
-
# * <tt>:include_blank</tt> - If set to true, an empty option will be created.
|
86
|
-
# * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something
|
90
|
+
# * <tt>:include_blank</tt> - If set to true, an empty option will be created. If set to a string, the string will be used as the option's content and the value will be empty.
|
91
|
+
# * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something.
|
87
92
|
# * Any other key creates standard HTML attributes for the tag.
|
88
93
|
#
|
89
94
|
# ==== Examples
|
90
95
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name")
|
91
96
|
# # <select id="people" name="people"><option value="1">David</option></select>
|
92
97
|
#
|
93
|
-
# select_tag "people", "
|
98
|
+
# select_tag "people", options_from_collection_for_select(@people, "id", "name", "1")
|
99
|
+
# # <select id="people" name="people"><option value="1" selected="selected">David</option></select>
|
100
|
+
#
|
101
|
+
# select_tag "people", raw("<option>David</option>")
|
94
102
|
# # => <select id="people" name="people"><option>David</option></select>
|
95
103
|
#
|
96
|
-
# select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>"
|
104
|
+
# select_tag "count", raw("<option>1</option><option>2</option><option>3</option><option>4</option>")
|
97
105
|
# # => <select id="count" name="count"><option>1</option><option>2</option>
|
98
106
|
# # <option>3</option><option>4</option></select>
|
99
107
|
#
|
100
|
-
# select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>"
|
108
|
+
# select_tag "colors", raw("<option>Red</option><option>Green</option><option>Blue</option>"), multiple: true
|
101
109
|
# # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
|
102
110
|
# # <option>Green</option><option>Blue</option></select>
|
103
111
|
#
|
104
|
-
# select_tag "locations", "<option>Home</option><option selected='selected'>Work</option><option>Out</option>"
|
112
|
+
# select_tag "locations", raw("<option>Home</option><option selected='selected'>Work</option><option>Out</option>")
|
105
113
|
# # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
|
106
114
|
# # <option>Out</option></select>
|
107
115
|
#
|
108
|
-
# select_tag "access", "<option>Read</option><option>Write</option>"
|
109
|
-
# # => <select class="form_input" id="
|
116
|
+
# select_tag "access", raw("<option>Read</option><option>Write</option>"), multiple: true, class: 'form_input', id: 'unique_id'
|
117
|
+
# # => <select class="form_input" id="unique_id" multiple="multiple" name="access[]"><option>Read</option>
|
110
118
|
# # <option>Write</option></select>
|
111
119
|
#
|
112
120
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true
|
113
|
-
# # => <select id="people" name="people"><option value=""></option><option value="1">David</option></select>
|
121
|
+
# # => <select id="people" name="people"><option value="" label=" "></option><option value="1">David</option></select>
|
122
|
+
#
|
123
|
+
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All"
|
124
|
+
# # => <select id="people" name="people"><option value="">All</option><option value="1">David</option></select>
|
114
125
|
#
|
115
126
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), prompt: "Select something"
|
116
127
|
# # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
|
117
128
|
#
|
118
|
-
# select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>"
|
129
|
+
# select_tag "destination", raw("<option>NYC</option><option>Paris</option><option>Rome</option>"), disabled: true
|
119
130
|
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
|
120
131
|
# # <option>Paris</option><option>Rome</option></select>
|
121
132
|
#
|
@@ -124,25 +135,28 @@ module ActionView
|
|
124
135
|
# # <option selected="selected">MasterCard</option></select>
|
125
136
|
def select_tag(name, option_tags = nil, options = {})
|
126
137
|
option_tags ||= ""
|
127
|
-
html_name = (options[:multiple] == true && !name.
|
138
|
+
html_name = (options[:multiple] == true && !name.end_with?("[]")) ? "#{name}[]" : name
|
128
139
|
|
129
140
|
if options.include?(:include_blank)
|
130
|
-
include_blank = options
|
141
|
+
include_blank = options[:include_blank]
|
142
|
+
options = options.except(:include_blank)
|
143
|
+
options_for_blank_options_tag = { value: "" }
|
131
144
|
|
132
145
|
if include_blank == true
|
133
|
-
include_blank =
|
146
|
+
include_blank = ""
|
147
|
+
options_for_blank_options_tag[:label] = " "
|
134
148
|
end
|
135
149
|
|
136
150
|
if include_blank
|
137
|
-
option_tags = content_tag(
|
151
|
+
option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags)
|
138
152
|
end
|
139
153
|
end
|
140
154
|
|
141
155
|
if prompt = options.delete(:prompt)
|
142
|
-
option_tags = content_tag(
|
156
|
+
option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
|
143
157
|
end
|
144
158
|
|
145
|
-
content_tag
|
159
|
+
content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
|
146
160
|
end
|
147
161
|
|
148
162
|
# Creates a standard text field; use these text fields to input smaller chunks of text like a username
|
@@ -153,6 +167,8 @@ module ActionView
|
|
153
167
|
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
|
154
168
|
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
|
155
169
|
# * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
|
170
|
+
# If set to true, use a translation is found in the current I18n locale
|
171
|
+
# (through helpers.placeholders.<modelname>.<attribute>).
|
156
172
|
# * Any other key creates standard HTML attributes for the tag.
|
157
173
|
#
|
158
174
|
# ==== Examples
|
@@ -225,7 +241,7 @@ module ActionView
|
|
225
241
|
# # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
|
226
242
|
# # type="hidden" value="" />
|
227
243
|
def hidden_field_tag(name, value = nil, options = {})
|
228
|
-
text_field_tag(name, value, options.
|
244
|
+
text_field_tag(name, value, options.merge(type: :hidden))
|
229
245
|
end
|
230
246
|
|
231
247
|
# Creates a file upload field. If you are using file uploads then you will also need
|
@@ -264,7 +280,7 @@ module ActionView
|
|
264
280
|
# file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
|
265
281
|
# # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
|
266
282
|
def file_field_tag(name, options = {})
|
267
|
-
text_field_tag(name, nil, options.
|
283
|
+
text_field_tag(name, nil, convert_direct_upload_option_to_url(options.merge(type: :file)))
|
268
284
|
end
|
269
285
|
|
270
286
|
# Creates a password field, a masked text field that will hide the users input behind a mask character.
|
@@ -297,7 +313,7 @@ module ActionView
|
|
297
313
|
# password_field_tag 'pin', '1234', maxlength: 4, size: 6, class: "pin_input"
|
298
314
|
# # => <input class="pin_input" id="pin" maxlength="4" name="pin" size="6" type="password" value="1234" />
|
299
315
|
def password_field_tag(name = "password", value = nil, options = {})
|
300
|
-
text_field_tag(name, value, options.
|
316
|
+
text_field_tag(name, value, options.merge(type: :password))
|
301
317
|
end
|
302
318
|
|
303
319
|
# Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions.
|
@@ -377,14 +393,14 @@ module ActionView
|
|
377
393
|
# * Any other key creates standard HTML options for the tag.
|
378
394
|
#
|
379
395
|
# ==== Examples
|
380
|
-
# radio_button_tag '
|
381
|
-
# # => <input id="
|
396
|
+
# radio_button_tag 'favorite_color', 'maroon'
|
397
|
+
# # => <input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" />
|
382
398
|
#
|
383
399
|
# radio_button_tag 'receive_updates', 'no', true
|
384
400
|
# # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
|
385
401
|
#
|
386
402
|
# radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
|
387
|
-
# # => <input disabled="disabled" id="
|
403
|
+
# # => <input disabled="disabled" id="time_slot_3:00_p.m." name="time_slot" type="radio" value="3:00 p.m." />
|
388
404
|
#
|
389
405
|
# radio_button_tag 'color', "green", true, class: "color_input"
|
390
406
|
# # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
|
@@ -408,42 +424,45 @@ module ActionView
|
|
408
424
|
# the form is processed normally, otherwise no action is taken.
|
409
425
|
# * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
|
410
426
|
# disabled version of the submit button when the form is submitted. This feature is
|
411
|
-
# provided by the unobtrusive JavaScript driver.
|
427
|
+
# provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
|
428
|
+
# pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
|
412
429
|
#
|
413
430
|
# ==== Examples
|
414
431
|
# submit_tag
|
415
|
-
# # => <input name="commit" type="submit" value="Save changes" />
|
432
|
+
# # => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
|
416
433
|
#
|
417
434
|
# submit_tag "Edit this article"
|
418
|
-
# # => <input name="commit" type="submit" value="Edit this article" />
|
435
|
+
# # => <input name="commit" data-disable-with="Edit this article" type="submit" value="Edit this article" />
|
419
436
|
#
|
420
437
|
# submit_tag "Save edits", disabled: true
|
421
|
-
# # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
|
438
|
+
# # => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
|
422
439
|
#
|
423
|
-
# submit_tag "Complete sale", data: { disable_with: "
|
424
|
-
# # => <input name="commit" data-disable-with="
|
440
|
+
# submit_tag "Complete sale", data: { disable_with: "Submitting..." }
|
441
|
+
# # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
|
425
442
|
#
|
426
443
|
# submit_tag nil, class: "form_submit"
|
427
444
|
# # => <input class="form_submit" name="commit" type="submit" />
|
428
445
|
#
|
429
446
|
# submit_tag "Edit", class: "edit_button"
|
430
|
-
# # => <input class="edit_button" name="commit" type="submit" value="Edit" />
|
447
|
+
# # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
|
431
448
|
#
|
432
449
|
# submit_tag "Save", data: { confirm: "Are you sure?" }
|
433
|
-
# # => <input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />
|
450
|
+
# # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
|
434
451
|
#
|
435
452
|
def submit_tag(value = "Save changes", options = {})
|
436
|
-
options = options.
|
437
|
-
|
438
|
-
|
453
|
+
options = options.deep_stringify_keys
|
454
|
+
tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)
|
455
|
+
set_default_disable_with value, tag_options
|
456
|
+
tag :input, tag_options
|
439
457
|
end
|
440
458
|
|
441
459
|
# Creates a button element that defines a <tt>submit</tt> button,
|
442
|
-
# <tt>reset</tt>button or a generic button which can be used in
|
460
|
+
# <tt>reset</tt> button or a generic button which can be used in
|
443
461
|
# JavaScript, for example. You can use the button tag as a regular
|
444
462
|
# submit tag but it isn't supported in legacy browsers. However,
|
445
|
-
# the button tag
|
446
|
-
# so this helper will also accept a block.
|
463
|
+
# the button tag does allow for richer labels such as images and emphasis,
|
464
|
+
# so this helper will also accept a block. By default, it will create
|
465
|
+
# a button tag with type <tt>submit</tt>, if type is not given.
|
447
466
|
#
|
448
467
|
# ==== Options
|
449
468
|
# * <tt>:data</tt> - This option can be used to add custom data attributes.
|
@@ -466,6 +485,15 @@ module ActionView
|
|
466
485
|
# button_tag
|
467
486
|
# # => <button name="button" type="submit">Button</button>
|
468
487
|
#
|
488
|
+
# button_tag 'Reset', type: 'reset'
|
489
|
+
# # => <button name="button" type="reset">Reset</button>
|
490
|
+
#
|
491
|
+
# button_tag 'Button', type: 'button'
|
492
|
+
# # => <button name="button" type="button">Button</button>
|
493
|
+
#
|
494
|
+
# button_tag 'Reset', type: 'reset', disabled: true
|
495
|
+
# # => <button name="button" type="reset" disabled="disabled">Reset</button>
|
496
|
+
#
|
469
497
|
# button_tag(type: 'button') do
|
470
498
|
# content_tag(:strong, 'Ask me!')
|
471
499
|
# end
|
@@ -473,6 +501,9 @@ module ActionView
|
|
473
501
|
# # <strong>Ask me!</strong>
|
474
502
|
# # </button>
|
475
503
|
#
|
504
|
+
# button_tag "Save", data: { confirm: "Are you sure?" }
|
505
|
+
# # => <button name="button" type="submit" data-confirm="Are you sure?">Save</button>
|
506
|
+
#
|
476
507
|
# button_tag "Checkout", data: { disable_with: "Please wait..." }
|
477
508
|
# # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
|
478
509
|
#
|
@@ -483,12 +514,12 @@ module ActionView
|
|
483
514
|
options ||= {}
|
484
515
|
end
|
485
516
|
|
486
|
-
options = {
|
517
|
+
options = { "name" => "button", "type" => "submit" }.merge!(options.stringify_keys)
|
487
518
|
|
488
519
|
if block_given?
|
489
520
|
content_tag :button, options, &block
|
490
521
|
else
|
491
|
-
content_tag :button, content_or_options ||
|
522
|
+
content_tag :button, content_or_options || "Button", options
|
492
523
|
end
|
493
524
|
end
|
494
525
|
|
@@ -509,22 +540,23 @@ module ActionView
|
|
509
540
|
#
|
510
541
|
# ==== Examples
|
511
542
|
# image_submit_tag("login.png")
|
512
|
-
# # => <input
|
543
|
+
# # => <input src="/assets/login.png" type="image" />
|
513
544
|
#
|
514
545
|
# image_submit_tag("purchase.png", disabled: true)
|
515
|
-
# # => <input
|
546
|
+
# # => <input disabled="disabled" src="/assets/purchase.png" type="image" />
|
516
547
|
#
|
517
548
|
# image_submit_tag("search.png", class: 'search_button', alt: 'Find')
|
518
|
-
# # => <input
|
549
|
+
# # => <input class="search_button" src="/assets/search.png" type="image" />
|
519
550
|
#
|
520
551
|
# image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
|
521
|
-
# # => <input
|
552
|
+
# # => <input class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
|
522
553
|
#
|
523
554
|
# image_submit_tag("save.png", data: { confirm: "Are you sure?" })
|
524
|
-
# # => <input
|
555
|
+
# # => <input src="/assets/save.png" data-confirm="Are you sure?" type="image" />
|
525
556
|
def image_submit_tag(source, options = {})
|
526
557
|
options = options.stringify_keys
|
527
|
-
|
558
|
+
src = path_to_image(source, skip_pipeline: options.delete("skip_pipeline"))
|
559
|
+
tag :input, { "type" => "image", "src" => src }.update(options)
|
528
560
|
end
|
529
561
|
|
530
562
|
# Creates a field set for grouping HTML form elements.
|
@@ -549,7 +581,7 @@ module ActionView
|
|
549
581
|
# # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
|
550
582
|
def field_set_tag(legend = nil, options = nil, &block)
|
551
583
|
output = tag(:fieldset, options, true)
|
552
|
-
output.safe_concat(content_tag(
|
584
|
+
output.safe_concat(content_tag("legend", legend)) unless legend.blank?
|
553
585
|
output.concat(capture(&block)) if block_given?
|
554
586
|
output.safe_concat("</fieldset>")
|
555
587
|
end
|
@@ -558,24 +590,63 @@ module ActionView
|
|
558
590
|
#
|
559
591
|
# ==== Options
|
560
592
|
# * Accepts the same options as text_field_tag.
|
593
|
+
#
|
594
|
+
# ==== Examples
|
595
|
+
# color_field_tag 'name'
|
596
|
+
# # => <input id="name" name="name" type="color" />
|
597
|
+
#
|
598
|
+
# color_field_tag 'color', '#DEF726'
|
599
|
+
# # => <input id="color" name="color" type="color" value="#DEF726" />
|
600
|
+
#
|
601
|
+
# color_field_tag 'color', nil, class: 'special_input'
|
602
|
+
# # => <input class="special_input" id="color" name="color" type="color" />
|
603
|
+
#
|
604
|
+
# color_field_tag 'color', '#DEF726', class: 'special_input', disabled: true
|
605
|
+
# # => <input disabled="disabled" class="special_input" id="color" name="color" type="color" value="#DEF726" />
|
561
606
|
def color_field_tag(name, value = nil, options = {})
|
562
|
-
text_field_tag(name, value, options.
|
607
|
+
text_field_tag(name, value, options.merge(type: :color))
|
563
608
|
end
|
564
609
|
|
565
610
|
# Creates a text field of type "search".
|
566
611
|
#
|
567
612
|
# ==== Options
|
568
613
|
# * Accepts the same options as text_field_tag.
|
614
|
+
#
|
615
|
+
# ==== Examples
|
616
|
+
# search_field_tag 'name'
|
617
|
+
# # => <input id="name" name="name" type="search" />
|
618
|
+
#
|
619
|
+
# search_field_tag 'search', 'Enter your search query here'
|
620
|
+
# # => <input id="search" name="search" type="search" value="Enter your search query here" />
|
621
|
+
#
|
622
|
+
# search_field_tag 'search', nil, class: 'special_input'
|
623
|
+
# # => <input class="special_input" id="search" name="search" type="search" />
|
624
|
+
#
|
625
|
+
# search_field_tag 'search', 'Enter your search query here', class: 'special_input', disabled: true
|
626
|
+
# # => <input disabled="disabled" class="special_input" id="search" name="search" type="search" value="Enter your search query here" />
|
569
627
|
def search_field_tag(name, value = nil, options = {})
|
570
|
-
text_field_tag(name, value, options.
|
628
|
+
text_field_tag(name, value, options.merge(type: :search))
|
571
629
|
end
|
572
630
|
|
573
631
|
# Creates a text field of type "tel".
|
574
632
|
#
|
575
633
|
# ==== Options
|
576
634
|
# * Accepts the same options as text_field_tag.
|
635
|
+
#
|
636
|
+
# ==== Examples
|
637
|
+
# telephone_field_tag 'name'
|
638
|
+
# # => <input id="name" name="name" type="tel" />
|
639
|
+
#
|
640
|
+
# telephone_field_tag 'tel', '0123456789'
|
641
|
+
# # => <input id="tel" name="tel" type="tel" value="0123456789" />
|
642
|
+
#
|
643
|
+
# telephone_field_tag 'tel', nil, class: 'special_input'
|
644
|
+
# # => <input class="special_input" id="tel" name="tel" type="tel" />
|
645
|
+
#
|
646
|
+
# telephone_field_tag 'tel', '0123456789', class: 'special_input', disabled: true
|
647
|
+
# # => <input disabled="disabled" class="special_input" id="tel" name="tel" type="tel" value="0123456789" />
|
577
648
|
def telephone_field_tag(name, value = nil, options = {})
|
578
|
-
text_field_tag(name, value, options.
|
649
|
+
text_field_tag(name, value, options.merge(type: :tel))
|
579
650
|
end
|
580
651
|
alias phone_field_tag telephone_field_tag
|
581
652
|
|
@@ -583,8 +654,21 @@ module ActionView
|
|
583
654
|
#
|
584
655
|
# ==== Options
|
585
656
|
# * Accepts the same options as text_field_tag.
|
657
|
+
#
|
658
|
+
# ==== Examples
|
659
|
+
# date_field_tag 'name'
|
660
|
+
# # => <input id="name" name="name" type="date" />
|
661
|
+
#
|
662
|
+
# date_field_tag 'date', '01/01/2014'
|
663
|
+
# # => <input id="date" name="date" type="date" value="01/01/2014" />
|
664
|
+
#
|
665
|
+
# date_field_tag 'date', nil, class: 'special_input'
|
666
|
+
# # => <input class="special_input" id="date" name="date" type="date" />
|
667
|
+
#
|
668
|
+
# date_field_tag 'date', '01/01/2014', class: 'special_input', disabled: true
|
669
|
+
# # => <input disabled="disabled" class="special_input" id="date" name="date" type="date" value="01/01/2014" />
|
586
670
|
def date_field_tag(name, value = nil, options = {})
|
587
|
-
text_field_tag(name, value, options.
|
671
|
+
text_field_tag(name, value, options.merge(type: :date))
|
588
672
|
end
|
589
673
|
|
590
674
|
# Creates a text field of type "time".
|
@@ -595,10 +679,10 @@ module ActionView
|
|
595
679
|
# * <tt>:step</tt> - The acceptable value granularity.
|
596
680
|
# * Otherwise accepts the same options as text_field_tag.
|
597
681
|
def time_field_tag(name, value = nil, options = {})
|
598
|
-
text_field_tag(name, value, options.
|
682
|
+
text_field_tag(name, value, options.merge(type: :time))
|
599
683
|
end
|
600
684
|
|
601
|
-
# Creates a text field of type "datetime".
|
685
|
+
# Creates a text field of type "datetime-local".
|
602
686
|
#
|
603
687
|
# === Options
|
604
688
|
# * <tt>:min</tt> - The minimum acceptable value.
|
@@ -606,19 +690,10 @@ module ActionView
|
|
606
690
|
# * <tt>:step</tt> - The acceptable value granularity.
|
607
691
|
# * Otherwise accepts the same options as text_field_tag.
|
608
692
|
def datetime_field_tag(name, value = nil, options = {})
|
609
|
-
text_field_tag(name, value, options.
|
693
|
+
text_field_tag(name, value, options.merge(type: "datetime-local"))
|
610
694
|
end
|
611
695
|
|
612
|
-
|
613
|
-
#
|
614
|
-
# === Options
|
615
|
-
# * <tt>:min</tt> - The minimum acceptable value.
|
616
|
-
# * <tt>:max</tt> - The maximum acceptable value.
|
617
|
-
# * <tt>:step</tt> - The acceptable value granularity.
|
618
|
-
# * Otherwise accepts the same options as text_field_tag.
|
619
|
-
def datetime_local_field_tag(name, value = nil, options = {})
|
620
|
-
text_field_tag(name, value, options.stringify_keys.update("type" => "datetime-local"))
|
621
|
-
end
|
696
|
+
alias datetime_local_field_tag datetime_field_tag
|
622
697
|
|
623
698
|
# Creates a text field of type "month".
|
624
699
|
#
|
@@ -628,7 +703,7 @@ module ActionView
|
|
628
703
|
# * <tt>:step</tt> - The acceptable value granularity.
|
629
704
|
# * Otherwise accepts the same options as text_field_tag.
|
630
705
|
def month_field_tag(name, value = nil, options = {})
|
631
|
-
text_field_tag(name, value, options.
|
706
|
+
text_field_tag(name, value, options.merge(type: :month))
|
632
707
|
end
|
633
708
|
|
634
709
|
# Creates a text field of type "week".
|
@@ -639,23 +714,49 @@ module ActionView
|
|
639
714
|
# * <tt>:step</tt> - The acceptable value granularity.
|
640
715
|
# * Otherwise accepts the same options as text_field_tag.
|
641
716
|
def week_field_tag(name, value = nil, options = {})
|
642
|
-
text_field_tag(name, value, options.
|
717
|
+
text_field_tag(name, value, options.merge(type: :week))
|
643
718
|
end
|
644
719
|
|
645
720
|
# Creates a text field of type "url".
|
646
721
|
#
|
647
722
|
# ==== Options
|
648
723
|
# * Accepts the same options as text_field_tag.
|
724
|
+
#
|
725
|
+
# ==== Examples
|
726
|
+
# url_field_tag 'name'
|
727
|
+
# # => <input id="name" name="name" type="url" />
|
728
|
+
#
|
729
|
+
# url_field_tag 'url', 'http://rubyonrails.org'
|
730
|
+
# # => <input id="url" name="url" type="url" value="http://rubyonrails.org" />
|
731
|
+
#
|
732
|
+
# url_field_tag 'url', nil, class: 'special_input'
|
733
|
+
# # => <input class="special_input" id="url" name="url" type="url" />
|
734
|
+
#
|
735
|
+
# url_field_tag 'url', 'http://rubyonrails.org', class: 'special_input', disabled: true
|
736
|
+
# # => <input disabled="disabled" class="special_input" id="url" name="url" type="url" value="http://rubyonrails.org" />
|
649
737
|
def url_field_tag(name, value = nil, options = {})
|
650
|
-
text_field_tag(name, value, options.
|
738
|
+
text_field_tag(name, value, options.merge(type: :url))
|
651
739
|
end
|
652
740
|
|
653
741
|
# Creates a text field of type "email".
|
654
742
|
#
|
655
743
|
# ==== Options
|
656
744
|
# * Accepts the same options as text_field_tag.
|
745
|
+
#
|
746
|
+
# ==== Examples
|
747
|
+
# email_field_tag 'name'
|
748
|
+
# # => <input id="name" name="name" type="email" />
|
749
|
+
#
|
750
|
+
# email_field_tag 'email', 'email@example.com'
|
751
|
+
# # => <input id="email" name="email" type="email" value="email@example.com" />
|
752
|
+
#
|
753
|
+
# email_field_tag 'email', nil, class: 'special_input'
|
754
|
+
# # => <input class="special_input" id="email" name="email" type="email" />
|
755
|
+
#
|
756
|
+
# email_field_tag 'email', 'email@example.com', class: 'special_input', disabled: true
|
757
|
+
# # => <input disabled="disabled" class="special_input" id="email" name="email" type="email" value="email@example.com" />
|
657
758
|
def email_field_tag(name, value = nil, options = {})
|
658
|
-
text_field_tag(name, value, options.
|
759
|
+
text_field_tag(name, value, options.merge(type: :email))
|
659
760
|
end
|
660
761
|
|
661
762
|
# Creates a number field.
|
@@ -665,12 +766,40 @@ module ActionView
|
|
665
766
|
# * <tt>:max</tt> - The maximum acceptable value.
|
666
767
|
# * <tt>:in</tt> - A range specifying the <tt>:min</tt> and
|
667
768
|
# <tt>:max</tt> values.
|
769
|
+
# * <tt>:within</tt> - Same as <tt>:in</tt>.
|
668
770
|
# * <tt>:step</tt> - The acceptable value granularity.
|
669
771
|
# * Otherwise accepts the same options as text_field_tag.
|
670
772
|
#
|
671
773
|
# ==== Examples
|
774
|
+
# number_field_tag 'quantity'
|
775
|
+
# # => <input id="quantity" name="quantity" type="number" />
|
776
|
+
#
|
777
|
+
# number_field_tag 'quantity', '1'
|
778
|
+
# # => <input id="quantity" name="quantity" type="number" value="1" />
|
779
|
+
#
|
780
|
+
# number_field_tag 'quantity', nil, class: 'special_input'
|
781
|
+
# # => <input class="special_input" id="quantity" name="quantity" type="number" />
|
782
|
+
#
|
783
|
+
# number_field_tag 'quantity', nil, min: 1
|
784
|
+
# # => <input id="quantity" name="quantity" min="1" type="number" />
|
785
|
+
#
|
786
|
+
# number_field_tag 'quantity', nil, max: 9
|
787
|
+
# # => <input id="quantity" name="quantity" max="9" type="number" />
|
788
|
+
#
|
672
789
|
# number_field_tag 'quantity', nil, in: 1...10
|
673
790
|
# # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
|
791
|
+
#
|
792
|
+
# number_field_tag 'quantity', nil, within: 1...10
|
793
|
+
# # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
|
794
|
+
#
|
795
|
+
# number_field_tag 'quantity', nil, min: 1, max: 10
|
796
|
+
# # => <input id="quantity" name="quantity" min="1" max="10" type="number" />
|
797
|
+
#
|
798
|
+
# number_field_tag 'quantity', nil, min: 1, max: 10, step: 2
|
799
|
+
# # => <input id="quantity" name="quantity" min="1" max="10" step="2" type="number" />
|
800
|
+
#
|
801
|
+
# number_field_tag 'quantity', '1', class: 'special_input', disabled: true
|
802
|
+
# # => <input disabled="disabled" class="special_input" id="quantity" name="quantity" type="number" value="1" />
|
674
803
|
def number_field_tag(name, value = nil, options = {})
|
675
804
|
options = options.stringify_keys
|
676
805
|
options["type"] ||= "number"
|
@@ -685,13 +814,16 @@ module ActionView
|
|
685
814
|
# ==== Options
|
686
815
|
# * Accepts the same options as number_field_tag.
|
687
816
|
def range_field_tag(name, value = nil, options = {})
|
688
|
-
number_field_tag(name, value, options.
|
817
|
+
number_field_tag(name, value, options.merge(type: :range))
|
689
818
|
end
|
690
819
|
|
691
820
|
# Creates the hidden UTF8 enforcer tag. Override this method in a helper
|
692
821
|
# to customize the tag.
|
693
822
|
def utf8_enforcer_tag
|
694
|
-
|
823
|
+
# Use raw HTML to ensure the value is written as an HTML entity; it
|
824
|
+
# needs to be the right character regardless of which encoding the
|
825
|
+
# browser infers.
|
826
|
+
'<input name="utf8" type="hidden" value="✓" />'.html_safe
|
695
827
|
end
|
696
828
|
|
697
829
|
private
|
@@ -720,23 +852,32 @@ module ActionView
|
|
720
852
|
|
721
853
|
def extra_tags_for_form(html_options)
|
722
854
|
authenticity_token = html_options.delete("authenticity_token")
|
723
|
-
method = html_options.delete("method").to_s
|
855
|
+
method = html_options.delete("method").to_s.downcase
|
724
856
|
|
725
|
-
method_tag =
|
726
|
-
|
857
|
+
method_tag = \
|
858
|
+
case method
|
859
|
+
when "get"
|
727
860
|
html_options["method"] = "get"
|
728
|
-
|
729
|
-
when
|
861
|
+
""
|
862
|
+
when "post", ""
|
730
863
|
html_options["method"] = "post"
|
731
|
-
token_tag(authenticity_token
|
864
|
+
token_tag(authenticity_token, form_options: {
|
865
|
+
action: html_options["action"],
|
866
|
+
method: "post"
|
867
|
+
})
|
732
868
|
else
|
733
869
|
html_options["method"] = "post"
|
734
|
-
method_tag(method) + token_tag(authenticity_token
|
735
|
-
|
870
|
+
method_tag(method) + token_tag(authenticity_token, form_options: {
|
871
|
+
action: html_options["action"],
|
872
|
+
method: method
|
873
|
+
})
|
874
|
+
end
|
736
875
|
|
737
|
-
|
738
|
-
|
739
|
-
|
876
|
+
if html_options.delete("enforce_utf8") { default_enforce_utf8 }
|
877
|
+
utf8_enforcer_tag + method_tag
|
878
|
+
else
|
879
|
+
method_tag
|
880
|
+
end
|
740
881
|
end
|
741
882
|
|
742
883
|
def form_tag_html(html_options)
|
@@ -744,8 +885,7 @@ module ActionView
|
|
744
885
|
tag(:form, html_options, true) + extra_tags
|
745
886
|
end
|
746
887
|
|
747
|
-
def
|
748
|
-
content = capture(&block)
|
888
|
+
def form_tag_with_body(html_options, content)
|
749
889
|
output = form_tag_html(html_options)
|
750
890
|
output << content
|
751
891
|
output.safe_concat("</form>")
|
@@ -753,7 +893,29 @@ module ActionView
|
|
753
893
|
|
754
894
|
# see http://www.w3.org/TR/html4/types.html#type-name
|
755
895
|
def sanitize_to_id(name)
|
756
|
-
name.to_s.delete(
|
896
|
+
name.to_s.delete("]").tr("^-a-zA-Z0-9:.", "_")
|
897
|
+
end
|
898
|
+
|
899
|
+
def set_default_disable_with(value, tag_options)
|
900
|
+
data = tag_options.fetch("data", {})
|
901
|
+
|
902
|
+
if tag_options["data-disable-with"] == false || data["disable_with"] == false
|
903
|
+
data.delete("disable_with")
|
904
|
+
elsif ActionView::Base.automatically_disable_submit_tag
|
905
|
+
disable_with_text = tag_options["data-disable-with"]
|
906
|
+
disable_with_text ||= data["disable_with"]
|
907
|
+
disable_with_text ||= value.to_s.clone
|
908
|
+
tag_options.deep_merge!("data" => { "disable_with" => disable_with_text })
|
909
|
+
end
|
910
|
+
|
911
|
+
tag_options.delete("data-disable-with")
|
912
|
+
end
|
913
|
+
|
914
|
+
def convert_direct_upload_option_to_url(options)
|
915
|
+
if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
|
916
|
+
options["data-direct-upload-url"] = rails_direct_uploads_url
|
917
|
+
end
|
918
|
+
options
|
757
919
|
end
|
758
920
|
end
|
759
921
|
end
|