actionview 4.2.10 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +141 -272
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_view/base.rb +33 -21
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/dependency_tracker.rb +52 -20
- data/lib/action_view/digestor.rb +86 -83
- data/lib/action_view/flows.rb +9 -11
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/active_model_helper.rb +8 -8
- data/lib/action_view/helpers/asset_tag_helper.rb +74 -38
- data/lib/action_view/helpers/asset_url_helper.rb +160 -59
- data/lib/action_view/helpers/atom_feed_helper.rb +16 -16
- data/lib/action_view/helpers/cache_helper.rb +90 -35
- data/lib/action_view/helpers/capture_helper.rb +7 -6
- data/lib/action_view/helpers/controller_helper.rb +3 -2
- data/lib/action_view/helpers/csrf_helper.rb +3 -3
- data/lib/action_view/helpers/date_helper.rb +156 -108
- data/lib/action_view/helpers/debug_helper.rb +3 -4
- data/lib/action_view/helpers/form_helper.rb +475 -94
- data/lib/action_view/helpers/form_options_helper.rb +87 -47
- data/lib/action_view/helpers/form_tag_helper.rb +88 -57
- data/lib/action_view/helpers/javascript_helper.rb +10 -10
- data/lib/action_view/helpers/number_helper.rb +76 -59
- data/lib/action_view/helpers/output_safety_helper.rb +34 -4
- data/lib/action_view/helpers/record_tag_helper.rb +12 -99
- data/lib/action_view/helpers/rendering_helper.rb +3 -3
- data/lib/action_view/helpers/sanitize_helper.rb +17 -14
- data/lib/action_view/helpers/tag_helper.rb +198 -73
- data/lib/action_view/helpers/tags/base.rb +132 -97
- data/lib/action_view/helpers/tags/check_box.rb +17 -17
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +9 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +68 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +3 -11
- data/lib/action_view/helpers/tags/collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/date_select.rb +36 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/label.rb +5 -1
- data/lib/action_view/helpers/tags/password_field.rb +1 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
- data/lib/action_view/helpers/tags/radio_button.rb +4 -4
- data/lib/action_view/helpers/tags/search_field.rb +12 -9
- data/lib/action_view/helpers/tags/select.rb +9 -9
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +5 -6
- data/lib/action_view/helpers/tags/translator.rb +15 -13
- data/lib/action_view/helpers/text_helper.rb +47 -30
- data/lib/action_view/helpers/translation_helper.rb +60 -30
- data/lib/action_view/helpers/url_helper.rb +132 -104
- data/lib/action_view/helpers.rb +1 -1
- data/lib/action_view/layouts.rb +59 -54
- data/lib/action_view/log_subscriber.rb +56 -7
- data/lib/action_view/lookup_context.rb +76 -61
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +28 -19
- data/lib/action_view/railtie.rb +30 -6
- data/lib/action_view/record_identifier.rb +51 -25
- data/lib/action_view/renderer/abstract_renderer.rb +19 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +55 -0
- data/lib/action_view/renderer/partial_renderer.rb +208 -206
- data/lib/action_view/renderer/renderer.rb +2 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +46 -48
- data/lib/action_view/renderer/template_renderer.rb +65 -66
- data/lib/action_view/rendering.rb +16 -9
- data/lib/action_view/routing_url_for.rb +25 -17
- data/lib/action_view/tasks/cache_digests.rake +23 -0
- data/lib/action_view/template/error.rb +14 -13
- data/lib/action_view/template/handlers/builder.rb +7 -7
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +9 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +81 -0
- data/lib/action_view/template/handlers/erb/erubis.rb +81 -0
- data/lib/action_view/template/handlers/erb.rb +9 -76
- data/lib/action_view/template/handlers/html.rb +9 -0
- data/lib/action_view/template/handlers/raw.rb +1 -3
- data/lib/action_view/template/handlers.rb +8 -6
- data/lib/action_view/template/html.rb +2 -4
- data/lib/action_view/template/resolver.rb +133 -109
- data/lib/action_view/template/text.rb +5 -8
- data/lib/action_view/template/types.rb +15 -17
- data/lib/action_view/template.rb +51 -28
- data/lib/action_view/test_case.rb +32 -27
- data/lib/action_view/testing/resolvers.rb +29 -31
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +26 -32
- data/lib/action_view.rb +5 -5
- data/lib/assets/compiled/rails-ujs.js +685 -0
- metadata +23 -23
- data/lib/action_view/tasks/dependencies.rake +0 -23
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
1
|
+
require "cgi"
|
|
2
|
+
require "erb"
|
|
3
|
+
require "action_view/helpers/form_helper"
|
|
4
|
+
require "active_support/core_ext/string/output_safety"
|
|
5
|
+
require "active_support/core_ext/array/extract_options"
|
|
6
|
+
require "active_support/core_ext/array/wrap"
|
|
7
7
|
|
|
8
8
|
module ActionView
|
|
9
9
|
# = Action View Form Option Helpers
|
|
@@ -18,10 +18,10 @@ module ActionView
|
|
|
18
18
|
#
|
|
19
19
|
# could become:
|
|
20
20
|
#
|
|
21
|
-
# <select name="post[category]">
|
|
22
|
-
# <option></option>
|
|
23
|
-
# <option>joke</option>
|
|
24
|
-
# <option>poem</option>
|
|
21
|
+
# <select name="post[category]" id="post_category">
|
|
22
|
+
# <option value=""></option>
|
|
23
|
+
# <option value="joke">joke</option>
|
|
24
|
+
# <option value="poem">poem</option>
|
|
25
25
|
# </select>
|
|
26
26
|
#
|
|
27
27
|
# Another common case is a select tag for a <tt>belongs_to</tt>-associated object.
|
|
@@ -32,11 +32,11 @@ module ActionView
|
|
|
32
32
|
#
|
|
33
33
|
# could become:
|
|
34
34
|
#
|
|
35
|
-
# <select name="post[person_id]">
|
|
35
|
+
# <select name="post[person_id]" id="post_person_id">
|
|
36
36
|
# <option value="">None</option>
|
|
37
37
|
# <option value="1">David</option>
|
|
38
|
-
# <option value="2" selected="selected">
|
|
39
|
-
# <option value="3">
|
|
38
|
+
# <option value="2" selected="selected">Eileen</option>
|
|
39
|
+
# <option value="3">Rafael</option>
|
|
40
40
|
# </select>
|
|
41
41
|
#
|
|
42
42
|
# * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.
|
|
@@ -45,11 +45,11 @@ module ActionView
|
|
|
45
45
|
#
|
|
46
46
|
# could become:
|
|
47
47
|
#
|
|
48
|
-
# <select name="post[person_id]">
|
|
48
|
+
# <select name="post[person_id]" id="post_person_id">
|
|
49
49
|
# <option value="">Select Person</option>
|
|
50
50
|
# <option value="1">David</option>
|
|
51
|
-
# <option value="2">
|
|
52
|
-
# <option value="3">
|
|
51
|
+
# <option value="2">Eileen</option>
|
|
52
|
+
# <option value="3">Rafael</option>
|
|
53
53
|
# </select>
|
|
54
54
|
#
|
|
55
55
|
# * <tt>:index</tt> - like the other form helpers, +select+ can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, +select+ expects this
|
|
@@ -71,19 +71,19 @@ module ActionView
|
|
|
71
71
|
#
|
|
72
72
|
# could become:
|
|
73
73
|
#
|
|
74
|
-
# <select name="post[category]">
|
|
75
|
-
# <option></option>
|
|
76
|
-
# <option>joke</option>
|
|
77
|
-
# <option>poem</option>
|
|
78
|
-
# <option disabled="disabled">restricted</option>
|
|
74
|
+
# <select name="post[category]" id="post_category">
|
|
75
|
+
# <option value=""></option>
|
|
76
|
+
# <option value="joke">joke</option>
|
|
77
|
+
# <option value="poem">poem</option>
|
|
78
|
+
# <option disabled="disabled" value="restricted">restricted</option>
|
|
79
79
|
# </select>
|
|
80
80
|
#
|
|
81
81
|
# When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled.
|
|
82
82
|
#
|
|
83
|
-
# collection_select(:post, :category_id, Category.all, :id, :name, {disabled:
|
|
83
|
+
# collection_select(:post, :category_id, Category.all, :id, :name, {disabled: -> (category) { category.archived? }})
|
|
84
84
|
#
|
|
85
85
|
# If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return:
|
|
86
|
-
# <select name="post[category_id]">
|
|
86
|
+
# <select name="post[category_id]" id="post_category_id">
|
|
87
87
|
# <option value="1" disabled="disabled">2008 stuff</option>
|
|
88
88
|
# <option value="2" disabled="disabled">Christmas</option>
|
|
89
89
|
# <option value="3">Jokes</option>
|
|
@@ -109,11 +109,11 @@ module ActionView
|
|
|
109
109
|
#
|
|
110
110
|
# would become:
|
|
111
111
|
#
|
|
112
|
-
# <select name="post[person_id]">
|
|
112
|
+
# <select name="post[person_id]" id="post_person_id">
|
|
113
113
|
# <option value=""></option>
|
|
114
114
|
# <option value="1" selected="selected">David</option>
|
|
115
|
-
# <option value="2">
|
|
116
|
-
# <option value="3">
|
|
115
|
+
# <option value="2">Eileen</option>
|
|
116
|
+
# <option value="3">Rafael</option>
|
|
117
117
|
# </select>
|
|
118
118
|
#
|
|
119
119
|
# assuming the associated person has ID 1.
|
|
@@ -192,7 +192,7 @@ module ActionView
|
|
|
192
192
|
# collection_select(:post, :author_id, Author.all, :id, :name_with_initial, prompt: true)
|
|
193
193
|
#
|
|
194
194
|
# If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return:
|
|
195
|
-
# <select name="post[author_id]">
|
|
195
|
+
# <select name="post[author_id]" id="post_author_id">
|
|
196
196
|
# <option value="">Please select</option>
|
|
197
197
|
# <option value="1" selected="selected">D. Heinemeier Hansson</option>
|
|
198
198
|
# <option value="2">D. Thomas</option>
|
|
@@ -243,7 +243,7 @@ module ActionView
|
|
|
243
243
|
#
|
|
244
244
|
# Possible output:
|
|
245
245
|
#
|
|
246
|
-
# <select name="city[country_id]">
|
|
246
|
+
# <select name="city[country_id]" id="city_country_id">
|
|
247
247
|
# <optgroup label="Africa">
|
|
248
248
|
# <option value="1">South Africa</option>
|
|
249
249
|
# <option value="3">Somalia</option>
|
|
@@ -268,10 +268,11 @@ module ActionView
|
|
|
268
268
|
# for more information.)
|
|
269
269
|
#
|
|
270
270
|
# You can also supply an array of ActiveSupport::TimeZone objects
|
|
271
|
-
# as +priority_zones
|
|
272
|
-
# (long) list.
|
|
273
|
-
#
|
|
274
|
-
#
|
|
271
|
+
# as +priority_zones+ so that they will be listed above the rest of the
|
|
272
|
+
# (long) list. You can use ActiveSupport::TimeZone.us_zones for a list
|
|
273
|
+
# of US time zones, ActiveSupport::TimeZone.country_zones(country_code)
|
|
274
|
+
# for another country's time zones, or a Regexp to select the zones of
|
|
275
|
+
# your choice.
|
|
275
276
|
#
|
|
276
277
|
# Finally, this method supports a <tt>:default</tt> option, which selects
|
|
277
278
|
# a default ActiveSupport::TimeZone if the object's time zone is +nil+.
|
|
@@ -302,17 +303,17 @@ module ActionView
|
|
|
302
303
|
# # => <option value="DKK">Kroner</option>
|
|
303
304
|
#
|
|
304
305
|
# options_for_select([ "VISA", "MasterCard" ], "MasterCard")
|
|
305
|
-
# # => <option>VISA</option>
|
|
306
|
-
# # => <option selected="selected">MasterCard</option>
|
|
306
|
+
# # => <option value="VISA">VISA</option>
|
|
307
|
+
# # => <option selected="selected" value="MasterCard">MasterCard</option>
|
|
307
308
|
#
|
|
308
309
|
# options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
|
|
309
310
|
# # => <option value="$20">Basic</option>
|
|
310
311
|
# # => <option value="$40" selected="selected">Plus</option>
|
|
311
312
|
#
|
|
312
313
|
# options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"])
|
|
313
|
-
# # => <option selected="selected">VISA</option>
|
|
314
|
-
# # => <option>MasterCard</option>
|
|
315
|
-
# # => <option selected="selected">Discover</option>
|
|
314
|
+
# # => <option selected="selected" value="VISA">VISA</option>
|
|
315
|
+
# # => <option value="MasterCard">MasterCard</option>
|
|
316
|
+
# # => <option selected="selected" value="Discover">Discover</option>
|
|
316
317
|
#
|
|
317
318
|
# You can optionally provide HTML attributes as the last element of the array.
|
|
318
319
|
#
|
|
@@ -351,18 +352,18 @@ module ActionView
|
|
|
351
352
|
return container if String === container
|
|
352
353
|
|
|
353
354
|
selected, disabled = extract_selected_and_disabled(selected).map do |r|
|
|
354
|
-
Array(r).map
|
|
355
|
+
Array(r).map(&:to_s)
|
|
355
356
|
end
|
|
356
357
|
|
|
357
358
|
container.map do |element|
|
|
358
359
|
html_attributes = option_html_attributes(element)
|
|
359
|
-
text, value = option_text_and_value(element).map
|
|
360
|
+
text, value = option_text_and_value(element).map(&:to_s)
|
|
360
361
|
|
|
361
362
|
html_attributes[:selected] ||= option_value_selected?(value, selected)
|
|
362
363
|
html_attributes[:disabled] ||= disabled && option_value_selected?(value, disabled)
|
|
363
364
|
html_attributes[:value] = value
|
|
364
365
|
|
|
365
|
-
content_tag_string(:option, text, html_attributes)
|
|
366
|
+
tag_builder.content_tag_string(:option, text, html_attributes)
|
|
366
367
|
end.join("\n").html_safe
|
|
367
368
|
end
|
|
368
369
|
|
|
@@ -456,7 +457,7 @@ module ActionView
|
|
|
456
457
|
option_tags = options_from_collection_for_select(
|
|
457
458
|
group.send(group_method), option_key_method, option_value_method, selected_key)
|
|
458
459
|
|
|
459
|
-
content_tag(
|
|
460
|
+
content_tag("optgroup".freeze, option_tags, label: group.send(group_label_method))
|
|
460
461
|
end.join.html_safe
|
|
461
462
|
end
|
|
462
463
|
|
|
@@ -528,7 +529,7 @@ module ActionView
|
|
|
528
529
|
body = "".html_safe
|
|
529
530
|
|
|
530
531
|
if prompt
|
|
531
|
-
body.safe_concat content_tag(
|
|
532
|
+
body.safe_concat content_tag("option".freeze, prompt_text(prompt), value: "")
|
|
532
533
|
end
|
|
533
534
|
|
|
534
535
|
grouped_options.each do |container|
|
|
@@ -541,14 +542,14 @@ module ActionView
|
|
|
541
542
|
end
|
|
542
543
|
|
|
543
544
|
html_attributes = { label: label }.merge!(html_attributes)
|
|
544
|
-
body.safe_concat content_tag(
|
|
545
|
+
body.safe_concat content_tag("optgroup".freeze, options_for_select(container, selected_key), html_attributes)
|
|
545
546
|
end
|
|
546
547
|
|
|
547
548
|
body
|
|
548
549
|
end
|
|
549
550
|
|
|
550
551
|
# Returns a string of option tags for pretty much any time zone in the
|
|
551
|
-
# world. Supply
|
|
552
|
+
# world. Supply an ActiveSupport::TimeZone name as +selected+ to have it
|
|
552
553
|
# marked as the selected option tag. You can also supply an array of
|
|
553
554
|
# ActiveSupport::TimeZone objects as +priority_zones+, so that they will
|
|
554
555
|
# be listed above the rest of the (long) list. (You can use
|
|
@@ -556,7 +557,7 @@ module ActionView
|
|
|
556
557
|
# of the US time zones, or a Regexp to select the zones of your choice)
|
|
557
558
|
#
|
|
558
559
|
# The +selected+ parameter must be either +nil+, or a string that names
|
|
559
|
-
#
|
|
560
|
+
# an ActiveSupport::TimeZone.
|
|
560
561
|
#
|
|
561
562
|
# By default, +model+ is the ActiveSupport::TimeZone constant (which can
|
|
562
563
|
# be obtained in Active Record as a value object). The only requirement
|
|
@@ -577,7 +578,7 @@ module ActionView
|
|
|
577
578
|
end
|
|
578
579
|
|
|
579
580
|
zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
|
|
580
|
-
zone_options.safe_concat content_tag(
|
|
581
|
+
zone_options.safe_concat content_tag("option".freeze, "-------------", value: "", disabled: true)
|
|
581
582
|
zone_options.safe_concat "\n"
|
|
582
583
|
|
|
583
584
|
zones = zones - priority_zones
|
|
@@ -644,6 +645,24 @@ module ActionView
|
|
|
644
645
|
# collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
|
|
645
646
|
# b.label(:"data-value" => b.value) { b.radio_button + b.text }
|
|
646
647
|
# end
|
|
648
|
+
#
|
|
649
|
+
# ==== Gotcha
|
|
650
|
+
#
|
|
651
|
+
# The HTML specification says when nothing is select on a collection of radio buttons
|
|
652
|
+
# web browsers do not send any value to server.
|
|
653
|
+
# Unfortunately this introduces a gotcha:
|
|
654
|
+
# if a +User+ model has a +category_id+ field and in the form no category is selected, no +category_id+ parameter is sent. So,
|
|
655
|
+
# any strong parameters idiom like:
|
|
656
|
+
#
|
|
657
|
+
# params.require(:user).permit(...)
|
|
658
|
+
#
|
|
659
|
+
# will raise an error since no <tt>{user: ...}</tt> will be present.
|
|
660
|
+
#
|
|
661
|
+
# To prevent this the helper generates an auxiliary hidden field before
|
|
662
|
+
# every collection of radio buttons. The hidden field has the same name as collection radio button and blank value.
|
|
663
|
+
#
|
|
664
|
+
# In case if you don't want the helper to generate this hidden field you can specify
|
|
665
|
+
# <tt>include_hidden: false</tt> option.
|
|
647
666
|
def collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
|
648
667
|
Tags::CollectionRadioButtons.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
|
|
649
668
|
end
|
|
@@ -707,6 +726,27 @@ module ActionView
|
|
|
707
726
|
# collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
|
|
708
727
|
# b.label(:"data-value" => b.value) { b.check_box + b.text }
|
|
709
728
|
# end
|
|
729
|
+
#
|
|
730
|
+
# ==== Gotcha
|
|
731
|
+
#
|
|
732
|
+
# When no selection is made for a collection of checkboxes most
|
|
733
|
+
# web browsers will not send any value.
|
|
734
|
+
#
|
|
735
|
+
# For example, if we have a +User+ model with +category_ids+ field and we
|
|
736
|
+
# have the following code in our update action:
|
|
737
|
+
#
|
|
738
|
+
# @user.update(params[:user])
|
|
739
|
+
#
|
|
740
|
+
# If no +category_ids+ are selected then we can safely assume this field
|
|
741
|
+
# will not be updated.
|
|
742
|
+
#
|
|
743
|
+
# This is possible thanks to a hidden field generated by the helper method
|
|
744
|
+
# for every collection of checkboxes.
|
|
745
|
+
# This hidden field is given the same field name as the checkboxes with a
|
|
746
|
+
# blank value.
|
|
747
|
+
#
|
|
748
|
+
# In the rare case you don't want this hidden field, you can pass the
|
|
749
|
+
# <tt>include_hidden: false</tt> option to the helper method.
|
|
710
750
|
def collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
|
711
751
|
Tags::CollectionCheckBoxes.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
|
|
712
752
|
end
|
|
@@ -760,7 +800,7 @@ module ActionView
|
|
|
760
800
|
end
|
|
761
801
|
|
|
762
802
|
def prompt_text(prompt)
|
|
763
|
-
prompt.kind_of?(String) ? prompt : I18n.translate(
|
|
803
|
+
prompt.kind_of?(String) ? prompt : I18n.translate("helpers.select.prompt", default: "Please select")
|
|
764
804
|
end
|
|
765
805
|
end
|
|
766
806
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
1
|
+
require "cgi"
|
|
2
|
+
require "action_view/helpers/tag_helper"
|
|
3
|
+
require "active_support/core_ext/string/output_safety"
|
|
4
|
+
require "active_support/core_ext/module/attribute_accessors"
|
|
5
5
|
|
|
6
6
|
module ActionView
|
|
7
7
|
# = Action View Form Tag Helpers
|
|
@@ -18,9 +18,9 @@ module ActionView
|
|
|
18
18
|
include TextHelper
|
|
19
19
|
|
|
20
20
|
mattr_accessor :embed_authenticity_token_in_remote_forms
|
|
21
|
-
self.embed_authenticity_token_in_remote_forms =
|
|
21
|
+
self.embed_authenticity_token_in_remote_forms = nil
|
|
22
22
|
|
|
23
|
-
# Starts a form tag that points the action to
|
|
23
|
+
# Starts a form tag that points the action to a url configured with <tt>url_for_options</tt> just like
|
|
24
24
|
# ActionController::Base#url_for. The method for the form defaults to POST.
|
|
25
25
|
#
|
|
26
26
|
# ==== Options
|
|
@@ -80,7 +80,7 @@ module ActionView
|
|
|
80
80
|
# associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
|
|
81
81
|
#
|
|
82
82
|
# ==== Options
|
|
83
|
-
# * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
|
|
83
|
+
# * <tt>:multiple</tt> - If set to true, the selection will allow multiple choices.
|
|
84
84
|
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
|
85
85
|
# * <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.
|
|
86
86
|
# * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something.
|
|
@@ -93,22 +93,22 @@ module ActionView
|
|
|
93
93
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name", "1")
|
|
94
94
|
# # <select id="people" name="people"><option value="1" selected="selected">David</option></select>
|
|
95
95
|
#
|
|
96
|
-
# select_tag "people", "<option>David</option>"
|
|
96
|
+
# select_tag "people", raw("<option>David</option>")
|
|
97
97
|
# # => <select id="people" name="people"><option>David</option></select>
|
|
98
98
|
#
|
|
99
|
-
# select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>"
|
|
99
|
+
# select_tag "count", raw("<option>1</option><option>2</option><option>3</option><option>4</option>")
|
|
100
100
|
# # => <select id="count" name="count"><option>1</option><option>2</option>
|
|
101
101
|
# # <option>3</option><option>4</option></select>
|
|
102
102
|
#
|
|
103
|
-
# select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>"
|
|
103
|
+
# select_tag "colors", raw("<option>Red</option><option>Green</option><option>Blue</option>"), multiple: true
|
|
104
104
|
# # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
|
|
105
105
|
# # <option>Green</option><option>Blue</option></select>
|
|
106
106
|
#
|
|
107
|
-
# select_tag "locations", "<option>Home</option><option selected='selected'>Work</option><option>Out</option>"
|
|
107
|
+
# select_tag "locations", raw("<option>Home</option><option selected='selected'>Work</option><option>Out</option>")
|
|
108
108
|
# # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
|
|
109
109
|
# # <option>Out</option></select>
|
|
110
110
|
#
|
|
111
|
-
# select_tag "access", "<option>Read</option><option>Write</option>"
|
|
111
|
+
# select_tag "access", raw("<option>Read</option><option>Write</option>"), multiple: true, class: 'form_input', id: 'unique_id'
|
|
112
112
|
# # => <select class="form_input" id="unique_id" multiple="multiple" name="access[]"><option>Read</option>
|
|
113
113
|
# # <option>Write</option></select>
|
|
114
114
|
#
|
|
@@ -121,7 +121,7 @@ module ActionView
|
|
|
121
121
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), prompt: "Select something"
|
|
122
122
|
# # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
|
|
123
123
|
#
|
|
124
|
-
# select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>"
|
|
124
|
+
# select_tag "destination", raw("<option>NYC</option><option>Paris</option><option>Rome</option>"), disabled: true
|
|
125
125
|
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
|
|
126
126
|
# # <option>Paris</option><option>Rome</option></select>
|
|
127
127
|
#
|
|
@@ -134,21 +134,23 @@ module ActionView
|
|
|
134
134
|
|
|
135
135
|
if options.include?(:include_blank)
|
|
136
136
|
include_blank = options.delete(:include_blank)
|
|
137
|
+
options_for_blank_options_tag = { value: "" }
|
|
137
138
|
|
|
138
139
|
if include_blank == true
|
|
139
|
-
include_blank =
|
|
140
|
+
include_blank = ""
|
|
141
|
+
options_for_blank_options_tag[:label] = " "
|
|
140
142
|
end
|
|
141
143
|
|
|
142
144
|
if include_blank
|
|
143
|
-
option_tags = content_tag(
|
|
145
|
+
option_tags = content_tag("option".freeze, include_blank, options_for_blank_options_tag).safe_concat(option_tags)
|
|
144
146
|
end
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
if prompt = options.delete(:prompt)
|
|
148
|
-
option_tags = content_tag(
|
|
150
|
+
option_tags = content_tag("option".freeze, prompt, value: "").safe_concat(option_tags)
|
|
149
151
|
end
|
|
150
152
|
|
|
151
|
-
content_tag
|
|
153
|
+
content_tag "select".freeze, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
|
|
152
154
|
end
|
|
153
155
|
|
|
154
156
|
# Creates a standard text field; use these text fields to input smaller chunks of text like a username
|
|
@@ -414,42 +416,45 @@ module ActionView
|
|
|
414
416
|
# the form is processed normally, otherwise no action is taken.
|
|
415
417
|
# * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
|
|
416
418
|
# disabled version of the submit button when the form is submitted. This feature is
|
|
417
|
-
# provided by the unobtrusive JavaScript driver.
|
|
419
|
+
# provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
|
|
420
|
+
# pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
|
|
418
421
|
#
|
|
419
422
|
# ==== Examples
|
|
420
423
|
# submit_tag
|
|
421
|
-
# # => <input name="commit" type="submit" value="Save changes" />
|
|
424
|
+
# # => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
|
|
422
425
|
#
|
|
423
426
|
# submit_tag "Edit this article"
|
|
424
|
-
# # => <input name="commit" type="submit" value="Edit this article" />
|
|
427
|
+
# # => <input name="commit" data-disable-with="Edit this article" type="submit" value="Edit this article" />
|
|
425
428
|
#
|
|
426
429
|
# submit_tag "Save edits", disabled: true
|
|
427
|
-
# # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
|
|
430
|
+
# # => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
|
|
428
431
|
#
|
|
429
|
-
# submit_tag "Complete sale", data: { disable_with: "
|
|
430
|
-
# # => <input name="commit" data-disable-with="
|
|
432
|
+
# submit_tag "Complete sale", data: { disable_with: "Submitting..." }
|
|
433
|
+
# # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
|
|
431
434
|
#
|
|
432
435
|
# submit_tag nil, class: "form_submit"
|
|
433
436
|
# # => <input class="form_submit" name="commit" type="submit" />
|
|
434
437
|
#
|
|
435
438
|
# submit_tag "Edit", class: "edit_button"
|
|
436
|
-
# # => <input class="edit_button" name="commit" type="submit" value="Edit" />
|
|
439
|
+
# # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
|
|
437
440
|
#
|
|
438
441
|
# submit_tag "Save", data: { confirm: "Are you sure?" }
|
|
439
|
-
# # => <input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />
|
|
442
|
+
# # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
|
|
440
443
|
#
|
|
441
444
|
def submit_tag(value = "Save changes", options = {})
|
|
442
|
-
options = options.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
+
options = options.deep_stringify_keys
|
|
446
|
+
tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)
|
|
447
|
+
set_default_disable_with value, tag_options
|
|
448
|
+
tag :input, tag_options
|
|
445
449
|
end
|
|
446
450
|
|
|
447
451
|
# Creates a button element that defines a <tt>submit</tt> button,
|
|
448
|
-
# <tt>reset</tt>button or a generic button which can be used in
|
|
452
|
+
# <tt>reset</tt> button or a generic button which can be used in
|
|
449
453
|
# JavaScript, for example. You can use the button tag as a regular
|
|
450
454
|
# submit tag but it isn't supported in legacy browsers. However,
|
|
451
|
-
# the button tag
|
|
452
|
-
# so this helper will also accept a block.
|
|
455
|
+
# the button tag does allow for richer labels such as images and emphasis,
|
|
456
|
+
# so this helper will also accept a block. By default, it will create
|
|
457
|
+
# a button tag with type `submit`, if type is not given.
|
|
453
458
|
#
|
|
454
459
|
# ==== Options
|
|
455
460
|
# * <tt>:data</tt> - This option can be used to add custom data attributes.
|
|
@@ -472,6 +477,15 @@ module ActionView
|
|
|
472
477
|
# button_tag
|
|
473
478
|
# # => <button name="button" type="submit">Button</button>
|
|
474
479
|
#
|
|
480
|
+
# button_tag 'Reset', type: 'reset'
|
|
481
|
+
# # => <button name="button" type="reset">Reset</button>
|
|
482
|
+
#
|
|
483
|
+
# button_tag 'Button', type: 'button'
|
|
484
|
+
# # => <button name="button" type="button">Button</button>
|
|
485
|
+
#
|
|
486
|
+
# button_tag 'Reset', type: 'reset', disabled: true
|
|
487
|
+
# # => <button name="button" type="reset" disabled="disabled">Reset</button>
|
|
488
|
+
#
|
|
475
489
|
# button_tag(type: 'button') do
|
|
476
490
|
# content_tag(:strong, 'Ask me!')
|
|
477
491
|
# end
|
|
@@ -479,6 +493,9 @@ module ActionView
|
|
|
479
493
|
# # <strong>Ask me!</strong>
|
|
480
494
|
# # </button>
|
|
481
495
|
#
|
|
496
|
+
# button_tag "Save", data: { confirm: "Are you sure?" }
|
|
497
|
+
# # => <button name="button" type="submit" data-confirm="Are you sure?">Save</button>
|
|
498
|
+
#
|
|
482
499
|
# button_tag "Checkout", data: { disable_with: "Please wait..." }
|
|
483
500
|
# # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
|
|
484
501
|
#
|
|
@@ -489,12 +506,12 @@ module ActionView
|
|
|
489
506
|
options ||= {}
|
|
490
507
|
end
|
|
491
508
|
|
|
492
|
-
options = {
|
|
509
|
+
options = { "name" => "button", "type" => "submit" }.merge!(options.stringify_keys)
|
|
493
510
|
|
|
494
511
|
if block_given?
|
|
495
512
|
content_tag :button, options, &block
|
|
496
513
|
else
|
|
497
|
-
content_tag :button, content_or_options ||
|
|
514
|
+
content_tag :button, content_or_options || "Button", options
|
|
498
515
|
end
|
|
499
516
|
end
|
|
500
517
|
|
|
@@ -555,7 +572,7 @@ module ActionView
|
|
|
555
572
|
# # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
|
|
556
573
|
def field_set_tag(legend = nil, options = nil, &block)
|
|
557
574
|
output = tag(:fieldset, options, true)
|
|
558
|
-
output.safe_concat(content_tag(
|
|
575
|
+
output.safe_concat(content_tag("legend".freeze, legend)) unless legend.blank?
|
|
559
576
|
output.concat(capture(&block)) if block_given?
|
|
560
577
|
output.safe_concat("</fieldset>")
|
|
561
578
|
end
|
|
@@ -656,7 +673,7 @@ module ActionView
|
|
|
656
673
|
text_field_tag(name, value, options.merge(type: :time))
|
|
657
674
|
end
|
|
658
675
|
|
|
659
|
-
# Creates a text field of type "datetime".
|
|
676
|
+
# Creates a text field of type "datetime-local".
|
|
660
677
|
#
|
|
661
678
|
# === Options
|
|
662
679
|
# * <tt>:min</tt> - The minimum acceptable value.
|
|
@@ -664,19 +681,10 @@ module ActionView
|
|
|
664
681
|
# * <tt>:step</tt> - The acceptable value granularity.
|
|
665
682
|
# * Otherwise accepts the same options as text_field_tag.
|
|
666
683
|
def datetime_field_tag(name, value = nil, options = {})
|
|
667
|
-
text_field_tag(name, value, options.merge(type:
|
|
684
|
+
text_field_tag(name, value, options.merge(type: "datetime-local"))
|
|
668
685
|
end
|
|
669
686
|
|
|
670
|
-
|
|
671
|
-
#
|
|
672
|
-
# === Options
|
|
673
|
-
# * <tt>:min</tt> - The minimum acceptable value.
|
|
674
|
-
# * <tt>:max</tt> - The maximum acceptable value.
|
|
675
|
-
# * <tt>:step</tt> - The acceptable value granularity.
|
|
676
|
-
# * Otherwise accepts the same options as text_field_tag.
|
|
677
|
-
def datetime_local_field_tag(name, value = nil, options = {})
|
|
678
|
-
text_field_tag(name, value, options.merge(type: 'datetime-local'))
|
|
679
|
-
end
|
|
687
|
+
alias datetime_local_field_tag datetime_field_tag
|
|
680
688
|
|
|
681
689
|
# Creates a text field of type "month".
|
|
682
690
|
#
|
|
@@ -776,10 +784,10 @@ module ActionView
|
|
|
776
784
|
# # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
|
|
777
785
|
#
|
|
778
786
|
# number_field_tag 'quantity', nil, min: 1, max: 10
|
|
779
|
-
# # => <input id="quantity" name="quantity" min="1" max="
|
|
787
|
+
# # => <input id="quantity" name="quantity" min="1" max="10" type="number" />
|
|
780
788
|
#
|
|
781
789
|
# number_field_tag 'quantity', nil, min: 1, max: 10, step: 2
|
|
782
|
-
# # => <input id="quantity" name="quantity" min="1" max="
|
|
790
|
+
# # => <input id="quantity" name="quantity" min="1" max="10" step="2" type="number" />
|
|
783
791
|
#
|
|
784
792
|
# number_field_tag 'quantity', '1', class: 'special_input', disabled: true
|
|
785
793
|
# # => <input disabled="disabled" class="special_input" id="quantity" name="quantity" type="number" value="1" />
|
|
@@ -835,19 +843,26 @@ module ActionView
|
|
|
835
843
|
|
|
836
844
|
def extra_tags_for_form(html_options)
|
|
837
845
|
authenticity_token = html_options.delete("authenticity_token")
|
|
838
|
-
method = html_options.delete("method").to_s
|
|
846
|
+
method = html_options.delete("method").to_s.downcase
|
|
839
847
|
|
|
840
|
-
method_tag =
|
|
841
|
-
|
|
848
|
+
method_tag = \
|
|
849
|
+
case method
|
|
850
|
+
when "get"
|
|
842
851
|
html_options["method"] = "get"
|
|
843
|
-
|
|
844
|
-
when
|
|
852
|
+
""
|
|
853
|
+
when "post", ""
|
|
845
854
|
html_options["method"] = "post"
|
|
846
|
-
token_tag(authenticity_token
|
|
855
|
+
token_tag(authenticity_token, form_options: {
|
|
856
|
+
action: html_options["action"],
|
|
857
|
+
method: "post"
|
|
858
|
+
})
|
|
847
859
|
else
|
|
848
860
|
html_options["method"] = "post"
|
|
849
|
-
method_tag(method) + token_tag(authenticity_token
|
|
850
|
-
|
|
861
|
+
method_tag(method) + token_tag(authenticity_token, form_options: {
|
|
862
|
+
action: html_options["action"],
|
|
863
|
+
method: method
|
|
864
|
+
})
|
|
865
|
+
end
|
|
851
866
|
|
|
852
867
|
if html_options.delete("enforce_utf8") { true }
|
|
853
868
|
utf8_enforcer_tag + method_tag
|
|
@@ -869,7 +884,23 @@ module ActionView
|
|
|
869
884
|
|
|
870
885
|
# see http://www.w3.org/TR/html4/types.html#type-name
|
|
871
886
|
def sanitize_to_id(name)
|
|
872
|
-
name.to_s.delete(
|
|
887
|
+
name.to_s.delete("]").tr("^-a-zA-Z0-9:.", "_")
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
def set_default_disable_with(value, tag_options)
|
|
891
|
+
return unless ActionView::Base.automatically_disable_submit_tag
|
|
892
|
+
data = tag_options["data"]
|
|
893
|
+
|
|
894
|
+
unless tag_options["data-disable-with"] == false || (data && data["disable_with"] == false)
|
|
895
|
+
disable_with_text = tag_options["data-disable-with"]
|
|
896
|
+
disable_with_text ||= data["disable_with"] if data
|
|
897
|
+
disable_with_text ||= value.to_s.clone
|
|
898
|
+
tag_options.deep_merge!("data" => { "disable_with" => disable_with_text })
|
|
899
|
+
else
|
|
900
|
+
data.delete("disable_with") if data
|
|
901
|
+
end
|
|
902
|
+
|
|
903
|
+
tag_options.delete("data-disable-with")
|
|
873
904
|
end
|
|
874
905
|
end
|
|
875
906
|
end
|