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,25 +1,36 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/attr_internal"
|
2
4
|
|
3
5
|
module ActionView
|
4
|
-
module Helpers
|
6
|
+
module Helpers #:nodoc:
|
5
7
|
# This module keeps all methods and behavior in ActionView
|
6
8
|
# that simply delegates to the controller.
|
7
9
|
module ControllerHelper #:nodoc:
|
8
10
|
attr_internal :controller, :request
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
CONTROLLER_DELEGATES = [:request_forgery_protection_token, :params,
|
13
|
+
:session, :cookies, :response, :headers, :flash, :action_name,
|
14
|
+
:controller_name, :controller_path]
|
15
|
+
|
16
|
+
delegate(*CONTROLLER_DELEGATES, to: :controller)
|
12
17
|
|
13
18
|
def assign_controller(controller)
|
14
19
|
if @_controller = controller
|
15
20
|
@_request = controller.request if controller.respond_to?(:request)
|
16
21
|
@_config = controller.config.inheritable_copy if controller.respond_to?(:config)
|
22
|
+
@_default_form_builder = controller.default_form_builder if controller.respond_to?(:default_form_builder)
|
17
23
|
end
|
18
24
|
end
|
19
25
|
|
20
26
|
def logger
|
21
27
|
controller.logger if controller.respond_to?(:logger)
|
22
28
|
end
|
29
|
+
|
30
|
+
def respond_to?(method_name, include_private = false)
|
31
|
+
return controller.respond_to?(method_name) if CONTROLLER_DELEGATES.include?(method_name.to_sym)
|
32
|
+
super
|
33
|
+
end
|
23
34
|
end
|
24
35
|
end
|
25
36
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
# = Action View CSP Helper
|
5
|
+
module Helpers #:nodoc:
|
6
|
+
module CspHelper
|
7
|
+
# Returns a meta tag "csp-nonce" with the per-session nonce value
|
8
|
+
# for allowing inline <script> tags.
|
9
|
+
#
|
10
|
+
# <head>
|
11
|
+
# <%= csp_meta_tag %>
|
12
|
+
# </head>
|
13
|
+
#
|
14
|
+
# This is used by the Rails UJS helper to create dynamically
|
15
|
+
# loaded inline <script> elements.
|
16
|
+
#
|
17
|
+
def csp_meta_tag(**options)
|
18
|
+
if content_security_policy?
|
19
|
+
options[:name] = "csp-nonce"
|
20
|
+
options[:content] = content_security_policy_nonce
|
21
|
+
tag("meta", options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView
|
2
4
|
# = Action View CSRF Helper
|
3
|
-
module Helpers
|
5
|
+
module Helpers #:nodoc:
|
4
6
|
module CsrfHelper
|
5
7
|
# Returns meta tags "csrf-param" and "csrf-token" with the name of the cross-site
|
6
8
|
# request forgery protection parameter and token, respectively.
|
@@ -14,14 +16,14 @@ module ActionView
|
|
14
16
|
#
|
15
17
|
# You don't need to use these tags for regular forms as they generate their own hidden fields.
|
16
18
|
#
|
17
|
-
# For AJAX requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
|
18
|
-
# "X-CSRF-Token" HTTP header. If you are using
|
19
|
+
# For AJAX requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
|
20
|
+
# "X-CSRF-Token" HTTP header. If you are using rails-ujs this happens automatically.
|
19
21
|
#
|
20
22
|
def csrf_meta_tags
|
21
|
-
if protect_against_forgery?
|
23
|
+
if defined?(protect_against_forgery?) && protect_against_forgery?
|
22
24
|
[
|
23
|
-
tag(
|
24
|
-
tag(
|
25
|
+
tag("meta", name: "csrf-param", content: request_forgery_protection_token),
|
26
|
+
tag("meta", name: "csrf-token", content: form_authenticity_token)
|
25
27
|
].join("\n").html_safe
|
26
28
|
end
|
27
29
|
end
|
@@ -1,12 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "action_view/helpers/tag_helper"
|
5
|
+
require "active_support/core_ext/array/extract_options"
|
6
|
+
require "active_support/core_ext/date/conversions"
|
7
|
+
require "active_support/core_ext/hash/slice"
|
8
|
+
require "active_support/core_ext/object/acts_like"
|
9
|
+
require "active_support/core_ext/object/with_options"
|
7
10
|
|
8
11
|
module ActionView
|
9
|
-
module Helpers
|
12
|
+
module Helpers #:nodoc:
|
10
13
|
# = Action View Date Helpers
|
11
14
|
#
|
12
15
|
# The Date Helper primarily creates select/option tags for different kinds of dates and times or date and time
|
@@ -19,6 +22,10 @@ module ActionView
|
|
19
22
|
# the <tt>select_month</tt> method would use simply "date" (which can be overwritten using <tt>:prefix</tt>) instead
|
20
23
|
# of \date[month].
|
21
24
|
module DateHelper
|
25
|
+
MINUTES_IN_YEAR = 525600
|
26
|
+
MINUTES_IN_QUARTER_YEAR = 131400
|
27
|
+
MINUTES_IN_THREE_QUARTERS_YEAR = 394200
|
28
|
+
|
22
29
|
# Reports the approximate distance in time between two Time, Date or DateTime objects or integers as seconds.
|
23
30
|
# Pass <tt>include_seconds: true</tt> if you want more detailed approximations when distance < 1 min, 29 secs.
|
24
31
|
# Distances are reported based on the following table:
|
@@ -64,71 +71,88 @@ module ActionView
|
|
64
71
|
# distance_of_time_in_words(from_time, to_time, include_seconds: true) # => about 6 years
|
65
72
|
# distance_of_time_in_words(to_time, from_time, include_seconds: true) # => about 6 years
|
66
73
|
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
|
74
|
+
#
|
75
|
+
# With the <tt>scope</tt> option, you can define a custom scope for Rails
|
76
|
+
# to look up the translation.
|
77
|
+
#
|
78
|
+
# For example you can define the following in your locale (e.g. en.yml).
|
79
|
+
#
|
80
|
+
# datetime:
|
81
|
+
# distance_in_words:
|
82
|
+
# short:
|
83
|
+
# about_x_hours:
|
84
|
+
# one: 'an hour'
|
85
|
+
# other: '%{count} hours'
|
86
|
+
#
|
87
|
+
# See https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml
|
88
|
+
# for more examples.
|
89
|
+
#
|
90
|
+
# Which will then result in the following:
|
91
|
+
#
|
92
|
+
# from_time = Time.now
|
93
|
+
# distance_of_time_in_words(from_time, from_time + 50.minutes, scope: 'datetime.distance_in_words.short') # => "an hour"
|
94
|
+
# distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short') # => "3 hours"
|
67
95
|
def distance_of_time_in_words(from_time, to_time = 0, options = {})
|
68
96
|
options = {
|
69
97
|
scope: :'datetime.distance_in_words'
|
70
98
|
}.merge!(options)
|
71
99
|
|
72
|
-
from_time = from_time
|
73
|
-
to_time =
|
100
|
+
from_time = normalize_distance_of_time_argument_to_time(from_time)
|
101
|
+
to_time = normalize_distance_of_time_argument_to_time(to_time)
|
74
102
|
from_time, to_time = to_time, from_time if from_time > to_time
|
75
|
-
distance_in_minutes = ((to_time - from_time)/60.0).round
|
103
|
+
distance_in_minutes = ((to_time - from_time) / 60.0).round
|
76
104
|
distance_in_seconds = (to_time - from_time).round
|
77
105
|
|
78
|
-
I18n.with_options :
|
106
|
+
I18n.with_options locale: options[:locale], scope: options[:scope] do |locale|
|
79
107
|
case distance_in_minutes
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
108
|
+
when 0..1
|
109
|
+
return distance_in_minutes == 0 ?
|
110
|
+
locale.t(:less_than_x_minutes, count: 1) :
|
111
|
+
locale.t(:x_minutes, count: distance_in_minutes) unless options[:include_seconds]
|
112
|
+
|
113
|
+
case distance_in_seconds
|
114
|
+
when 0..4 then locale.t :less_than_x_seconds, count: 5
|
115
|
+
when 5..9 then locale.t :less_than_x_seconds, count: 10
|
116
|
+
when 10..19 then locale.t :less_than_x_seconds, count: 20
|
117
|
+
when 20..39 then locale.t :half_a_minute
|
118
|
+
when 40..59 then locale.t :less_than_x_minutes, count: 1
|
119
|
+
else locale.t :x_minutes, count: 1
|
120
|
+
end
|
121
|
+
|
122
|
+
when 2...45 then locale.t :x_minutes, count: distance_in_minutes
|
123
|
+
when 45...90 then locale.t :about_x_hours, count: 1
|
96
124
|
# 90 mins up to 24 hours
|
97
|
-
|
125
|
+
when 90...1440 then locale.t :about_x_hours, count: (distance_in_minutes.to_f / 60.0).round
|
98
126
|
# 24 hours up to 42 hours
|
99
|
-
|
127
|
+
when 1440...2520 then locale.t :x_days, count: 1
|
100
128
|
# 42 hours up to 30 days
|
101
|
-
|
129
|
+
when 2520...43200 then locale.t :x_days, count: (distance_in_minutes.to_f / 1440.0).round
|
102
130
|
# 30 days up to 60 days
|
103
|
-
|
131
|
+
when 43200...86400 then locale.t :about_x_months, count: (distance_in_minutes.to_f / 43200.0).round
|
104
132
|
# 60 days up to 365 days
|
105
|
-
|
133
|
+
when 86400...525600 then locale.t :x_months, count: (distance_in_minutes.to_f / 43200.0).round
|
134
|
+
else
|
135
|
+
from_year = from_time.year
|
136
|
+
from_year += 1 if from_time.month >= 3
|
137
|
+
to_year = to_time.year
|
138
|
+
to_year -= 1 if to_time.month < 3
|
139
|
+
leap_years = (from_year > to_year) ? 0 : (from_year..to_year).count { |x| Date.leap?(x) }
|
140
|
+
minute_offset_for_leap_year = leap_years * 1440
|
141
|
+
# Discount the leap year days when calculating year distance.
|
142
|
+
# e.g. if there are 20 leap year days between 2 dates having the same day
|
143
|
+
# and month then the based on 365 days calculation
|
144
|
+
# the distance in years will come out to over 80 years when in written
|
145
|
+
# English it would read better as about 80 years.
|
146
|
+
minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
|
147
|
+
remainder = (minutes_with_offset % MINUTES_IN_YEAR)
|
148
|
+
distance_in_years = (minutes_with_offset.div MINUTES_IN_YEAR)
|
149
|
+
if remainder < MINUTES_IN_QUARTER_YEAR
|
150
|
+
locale.t(:about_x_years, count: distance_in_years)
|
151
|
+
elsif remainder < MINUTES_IN_THREE_QUARTERS_YEAR
|
152
|
+
locale.t(:over_x_years, count: distance_in_years)
|
106
153
|
else
|
107
|
-
|
108
|
-
|
109
|
-
fyear += 1 if from_time.month >= 3
|
110
|
-
tyear = to_time.year
|
111
|
-
tyear -= 1 if to_time.month < 3
|
112
|
-
leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| Date.leap?(x)}
|
113
|
-
minute_offset_for_leap_year = leap_years * 1440
|
114
|
-
# Discount the leap year days when calculating year distance.
|
115
|
-
# e.g. if there are 20 leap year days between 2 dates having the same day
|
116
|
-
# and month then the based on 365 days calculation
|
117
|
-
# the distance in years will come out to over 80 years when in written
|
118
|
-
# English it would read better as about 80 years.
|
119
|
-
minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
|
120
|
-
else
|
121
|
-
minutes_with_offset = distance_in_minutes
|
122
|
-
end
|
123
|
-
remainder = (minutes_with_offset % 525600)
|
124
|
-
distance_in_years = (minutes_with_offset.div 525600)
|
125
|
-
if remainder < 131400
|
126
|
-
locale.t(:about_x_years, :count => distance_in_years)
|
127
|
-
elsif remainder < 394200
|
128
|
-
locale.t(:over_x_years, :count => distance_in_years)
|
129
|
-
else
|
130
|
-
locale.t(:almost_x_years, :count => distance_in_years + 1)
|
131
|
-
end
|
154
|
+
locale.t(:almost_x_years, count: distance_in_years + 1)
|
155
|
+
end
|
132
156
|
end
|
133
157
|
end
|
134
158
|
end
|
@@ -149,8 +173,8 @@ module ActionView
|
|
149
173
|
#
|
150
174
|
# Note that you cannot pass a <tt>Numeric</tt> value to <tt>time_ago_in_words</tt>.
|
151
175
|
#
|
152
|
-
def time_ago_in_words(from_time,
|
153
|
-
distance_of_time_in_words(from_time, Time.now,
|
176
|
+
def time_ago_in_words(from_time, options = {})
|
177
|
+
distance_of_time_in_words(from_time, Time.now, options)
|
154
178
|
end
|
155
179
|
|
156
180
|
alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
|
@@ -173,12 +197,15 @@ module ActionView
|
|
173
197
|
# and +:name+ (string). A format string would be something like "%{name} (%<number>02d)" for example.
|
174
198
|
# See <tt>Kernel.sprintf</tt> for documentation on format sequences.
|
175
199
|
# * <tt>:date_separator</tt> - Specifies a string to separate the date fields. Default is "" (i.e. nothing).
|
176
|
-
# * <tt>:
|
200
|
+
# * <tt>:time_separator</tt> - Specifies a string to separate the time fields. Default is " : ".
|
201
|
+
# * <tt>:datetime_separator</tt>- Specifies a string to separate the date and time fields. Default is " — ".
|
202
|
+
# * <tt>:start_year</tt> - Set the start year for the year select. Default is <tt>Date.today.year - 5</tt> if
|
177
203
|
# you are creating new record. While editing existing record, <tt>:start_year</tt> defaults to
|
178
204
|
# the current selected year minus 5.
|
179
205
|
# * <tt>:end_year</tt> - Set the end year for the year select. Default is <tt>Date.today.year + 5</tt> if
|
180
206
|
# you are creating new record. While editing existing record, <tt>:end_year</tt> defaults to
|
181
207
|
# the current selected year plus 5.
|
208
|
+
# * <tt>:year_format</tt> - Set format of years for year select. Lambda should be passed.
|
182
209
|
# * <tt>:discard_day</tt> - Set to true if you don't want to show a day select. This includes the day
|
183
210
|
# as a hidden field instead of showing a select field. Also note that this implicitly sets the day to be the
|
184
211
|
# first of the given month in order to not create invalid dates like 31 February.
|
@@ -192,15 +219,18 @@ module ActionView
|
|
192
219
|
# the respective locale (e.g. [:year, :month, :day] in the en locale that ships with Rails).
|
193
220
|
# * <tt>:include_blank</tt> - Include a blank option in every select field so it's possible to set empty
|
194
221
|
# dates.
|
195
|
-
# * <tt>:default</tt> - Set a default date if the affected date isn't set or is nil
|
222
|
+
# * <tt>:default</tt> - Set a default date if the affected date isn't set or is +nil+.
|
196
223
|
# * <tt>:selected</tt> - Set a date that overrides the actual value.
|
197
224
|
# * <tt>:disabled</tt> - Set to true if you want show the select fields as disabled.
|
198
225
|
# * <tt>:prompt</tt> - Set to true (for a generic prompt), a prompt string or a hash of prompt strings
|
199
226
|
# for <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>, <tt>:minute</tt> and <tt>:second</tt>.
|
200
227
|
# Setting this option prepends a select option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds)
|
201
228
|
# or the given prompt string.
|
202
|
-
# * <tt>:with_css_classes</tt>
|
203
|
-
# automatically set classes 'year', 'month', 'day', 'hour', 'minute' and 'second'
|
229
|
+
# * <tt>:with_css_classes</tt> - Set to true or a hash of strings. Use true if you want to assign generic styles for
|
230
|
+
# select tags. This automatically set classes 'year', 'month', 'day', 'hour', 'minute' and 'second'. A hash of
|
231
|
+
# strings for <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>, <tt>:minute</tt>, <tt>:second</tt>
|
232
|
+
# will extend the select type with the given value. Use +html_options+ to modify every select tag in the set.
|
233
|
+
# * <tt>:use_hidden</tt> - Set to true if you only want to generate hidden input tags.
|
204
234
|
#
|
205
235
|
# If anything is passed in the +html_options+ hash it will be applied to every select tag in the set.
|
206
236
|
#
|
@@ -236,7 +266,7 @@ module ActionView
|
|
236
266
|
# date_select("article", "written_on", default: 3.days.from_now)
|
237
267
|
#
|
238
268
|
# # Generates a date select that when POSTed is stored in the article variable, in the written_on attribute
|
239
|
-
# # which is set in the form with
|
269
|
+
# # which is set in the form with today's date, regardless of the value in the Active Record object.
|
240
270
|
# date_select("article", "written_on", selected: Date.today)
|
241
271
|
#
|
242
272
|
# # Generates a date select that when POSTed is stored in the credit_card variable, in the bill_due attribute
|
@@ -246,6 +276,9 @@ module ActionView
|
|
246
276
|
# # Generates a date select with custom prompts.
|
247
277
|
# date_select("article", "written_on", prompt: { day: 'Select day', month: 'Select month', year: 'Select year' })
|
248
278
|
#
|
279
|
+
# # Generates a date select with custom year format.
|
280
|
+
# date_select("article", "written_on", year_format: ->(year) { "Heisei #{year - 1988}" })
|
281
|
+
#
|
249
282
|
# The selects are prepared for multi-parameter assignment to an Active Record object.
|
250
283
|
#
|
251
284
|
# Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that
|
@@ -272,16 +305,16 @@ module ActionView
|
|
272
305
|
# # the sunrise attribute.
|
273
306
|
# time_select("article", "start_time", include_seconds: true)
|
274
307
|
#
|
275
|
-
# # You can set the <tt>:minute_step</tt> to 15 which will give you: 00, 15, 30 and 45.
|
276
|
-
# time_select 'game', 'game_time', {minute_step: 15}
|
308
|
+
# # You can set the <tt>:minute_step</tt> to 15 which will give you: 00, 15, 30, and 45.
|
309
|
+
# time_select 'game', 'game_time', { minute_step: 15 }
|
277
310
|
#
|
278
311
|
# # Creates a time select tag with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
|
279
|
-
# time_select("article", "written_on", prompt: {hour: 'Choose hour', minute: 'Choose minute', second: 'Choose seconds'})
|
280
|
-
# time_select("article", "written_on", prompt: {hour: true}) # generic prompt for hours
|
312
|
+
# time_select("article", "written_on", prompt: { hour: 'Choose hour', minute: 'Choose minute', second: 'Choose seconds' })
|
313
|
+
# time_select("article", "written_on", prompt: { hour: true }) # generic prompt for hours
|
281
314
|
# time_select("article", "written_on", prompt: true) # generic prompts for all
|
282
315
|
#
|
283
316
|
# # You can set :ampm option to true which will show the hours as: 12 PM, 01 AM .. 11 PM.
|
284
|
-
# time_select 'game', 'game_time', {ampm: true}
|
317
|
+
# time_select 'game', 'game_time', { ampm: true }
|
285
318
|
#
|
286
319
|
# The selects are prepared for multi-parameter assignment to an Active Record object.
|
287
320
|
#
|
@@ -317,8 +350,8 @@ module ActionView
|
|
317
350
|
# datetime_select("article", "written_on", discard_type: true)
|
318
351
|
#
|
319
352
|
# # Generates a datetime select with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
|
320
|
-
# datetime_select("article", "written_on", prompt: {day: 'Choose day', month: 'Choose month', year: 'Choose year'})
|
321
|
-
# datetime_select("article", "written_on", prompt: {hour: true}) # generic prompt for hours
|
353
|
+
# datetime_select("article", "written_on", prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
|
354
|
+
# datetime_select("article", "written_on", prompt: { hour: true }) # generic prompt for hours
|
322
355
|
# datetime_select("article", "written_on", prompt: true) # generic prompts for all
|
323
356
|
#
|
324
357
|
# The selects are prepared for multi-parameter assignment to an Active Record object.
|
@@ -326,7 +359,7 @@ module ActionView
|
|
326
359
|
Tags::DatetimeSelect.new(object_name, method, self, options, html_options).render
|
327
360
|
end
|
328
361
|
|
329
|
-
# Returns a set of
|
362
|
+
# Returns a set of HTML select-tags (one for year, month, day, hour, minute, and second) pre-selected with the
|
330
363
|
# +datetime+. It's also possible to explicitly set the order of the tags using the <tt>:order</tt> option with
|
331
364
|
# an array of symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in the desired order. If you do not
|
332
365
|
# supply a Symbol, it will be appended onto the <tt>:order</tt> passed in. You can also add
|
@@ -368,14 +401,14 @@ module ActionView
|
|
368
401
|
# select_datetime(my_date_time, prefix: 'payday')
|
369
402
|
#
|
370
403
|
# # Generates a datetime select with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
|
371
|
-
# select_datetime(my_date_time, prompt: {day: 'Choose day', month: 'Choose month', year: 'Choose year'})
|
372
|
-
# select_datetime(my_date_time, prompt: {hour: true}) # generic prompt for hours
|
404
|
+
# select_datetime(my_date_time, prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
|
405
|
+
# select_datetime(my_date_time, prompt: { hour: true }) # generic prompt for hours
|
373
406
|
# select_datetime(my_date_time, prompt: true) # generic prompts for all
|
374
407
|
def select_datetime(datetime = Time.current, options = {}, html_options = {})
|
375
408
|
DateTimeSelector.new(datetime, options, html_options).select_datetime
|
376
409
|
end
|
377
410
|
|
378
|
-
# Returns a set of
|
411
|
+
# Returns a set of HTML select-tags (one for year, month, and day) pre-selected with the +date+.
|
379
412
|
# It's possible to explicitly set the order of the tags using the <tt>:order</tt> option with an array of
|
380
413
|
# symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in the desired order.
|
381
414
|
# If the array passed to the <tt>:order</tt> option does not contain all the three symbols, all tags will be hidden.
|
@@ -407,14 +440,14 @@ module ActionView
|
|
407
440
|
# select_date(my_date, prefix: 'payday')
|
408
441
|
#
|
409
442
|
# # Generates a date select with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
|
410
|
-
# select_date(my_date, prompt: {day: 'Choose day', month: 'Choose month', year: 'Choose year'})
|
411
|
-
# select_date(my_date, prompt: {hour: true}) # generic prompt for hours
|
443
|
+
# select_date(my_date, prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
|
444
|
+
# select_date(my_date, prompt: { hour: true }) # generic prompt for hours
|
412
445
|
# select_date(my_date, prompt: true) # generic prompts for all
|
413
446
|
def select_date(date = Date.current, options = {}, html_options = {})
|
414
447
|
DateTimeSelector.new(date, options, html_options).select_date
|
415
448
|
end
|
416
449
|
|
417
|
-
# Returns a set of
|
450
|
+
# Returns a set of HTML select-tags (one for hour and minute).
|
418
451
|
# You can set <tt>:time_separator</tt> key to format the output, and
|
419
452
|
# the <tt>:include_seconds</tt> option to include an input for seconds.
|
420
453
|
#
|
@@ -447,8 +480,8 @@ module ActionView
|
|
447
480
|
# select_time(my_time, start_hour: 2, end_hour: 14)
|
448
481
|
#
|
449
482
|
# # Generates a time select with a custom prompt. Use <tt>:prompt</tt> to true for generic prompts.
|
450
|
-
# select_time(my_time, prompt: {day: 'Choose day', month: 'Choose month', year: 'Choose year'})
|
451
|
-
# select_time(my_time, prompt: {hour: true}) # generic prompt for hours
|
483
|
+
# select_time(my_time, prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
|
484
|
+
# select_time(my_time, prompt: { hour: true }) # generic prompt for hours
|
452
485
|
# select_time(my_time, prompt: true) # generic prompts for all
|
453
486
|
def select_time(datetime = Time.current, options = {}, html_options = {})
|
454
487
|
DateTimeSelector.new(datetime, options, html_options).select_time
|
@@ -458,7 +491,7 @@ module ActionView
|
|
458
491
|
# The <tt>datetime</tt> can be either a +Time+ or +DateTime+ object or an integer.
|
459
492
|
# Override the field name using the <tt>:field_name</tt> option, 'second' by default.
|
460
493
|
#
|
461
|
-
# my_time = Time.now + 16.
|
494
|
+
# my_time = Time.now + 16.seconds
|
462
495
|
#
|
463
496
|
# # Generates a select field for seconds that defaults to the seconds for the time in my_time.
|
464
497
|
# select_second(my_time)
|
@@ -482,7 +515,7 @@ module ActionView
|
|
482
515
|
# selected. The <tt>datetime</tt> can be either a +Time+ or +DateTime+ object or an integer.
|
483
516
|
# Override the field name using the <tt>:field_name</tt> option, 'minute' by default.
|
484
517
|
#
|
485
|
-
# my_time = Time.now +
|
518
|
+
# my_time = Time.now + 10.minutes
|
486
519
|
#
|
487
520
|
# # Generates a select field for minutes that defaults to the minutes for the time in my_time.
|
488
521
|
# select_minute(my_time)
|
@@ -631,7 +664,7 @@ module ActionView
|
|
631
664
|
DateTimeSelector.new(date, options, html_options).select_year
|
632
665
|
end
|
633
666
|
|
634
|
-
# Returns an
|
667
|
+
# Returns an HTML time tag for the given date or time.
|
635
668
|
#
|
636
669
|
# time_tag Date.today # =>
|
637
670
|
# <time datetime="2010-11-04">November 04, 2010</time>
|
@@ -639,8 +672,6 @@ module ActionView
|
|
639
672
|
# <time datetime="2010-11-04T17:55:45+01:00">November 04, 2010 17:55</time>
|
640
673
|
# time_tag Date.yesterday, 'Yesterday' # =>
|
641
674
|
# <time datetime="2010-11-03">Yesterday</time>
|
642
|
-
# time_tag Date.today, pubdate: true # =>
|
643
|
-
# <time datetime="2010-11-04" pubdate="pubdate">November 04, 2010</time>
|
644
675
|
# time_tag Date.today, datetime: Date.today.strftime('%G-W%V') # =>
|
645
676
|
# <time datetime="2010-W44">November 04, 2010</time>
|
646
677
|
#
|
@@ -651,19 +682,29 @@ module ActionView
|
|
651
682
|
def time_tag(date_or_time, *args, &block)
|
652
683
|
options = args.extract_options!
|
653
684
|
format = options.delete(:format) || :long
|
654
|
-
content = args.first || I18n.l(date_or_time, :
|
655
|
-
datetime = date_or_time.acts_like?(:time) ? date_or_time.xmlschema : date_or_time.iso8601
|
685
|
+
content = args.first || I18n.l(date_or_time, format: format)
|
656
686
|
|
657
|
-
content_tag(
|
687
|
+
content_tag("time", content, options.reverse_merge(datetime: date_or_time.iso8601), &block)
|
658
688
|
end
|
689
|
+
|
690
|
+
private
|
691
|
+
def normalize_distance_of_time_argument_to_time(value)
|
692
|
+
if value.is_a?(Numeric)
|
693
|
+
Time.at(value)
|
694
|
+
elsif value.respond_to?(:to_time)
|
695
|
+
value.to_time
|
696
|
+
else
|
697
|
+
raise ArgumentError, "#{value.inspect} can't be converted to a Time value"
|
698
|
+
end
|
699
|
+
end
|
659
700
|
end
|
660
701
|
|
661
702
|
class DateTimeSelector #:nodoc:
|
662
703
|
include ActionView::Helpers::TagHelper
|
663
704
|
|
664
|
-
DEFAULT_PREFIX =
|
705
|
+
DEFAULT_PREFIX = "date"
|
665
706
|
POSITION = {
|
666
|
-
:
|
707
|
+
year: 1, month: 2, day: 3, hour: 4, minute: 5, second: 6
|
667
708
|
}.freeze
|
668
709
|
|
669
710
|
AMPM_TRANSLATION = Hash[
|
@@ -679,8 +720,8 @@ module ActionView
|
|
679
720
|
@options = options.dup
|
680
721
|
@html_options = html_options.dup
|
681
722
|
@datetime = datetime
|
682
|
-
@options[:datetime_separator] ||=
|
683
|
-
@options[:time_separator] ||=
|
723
|
+
@options[:datetime_separator] ||= " — "
|
724
|
+
@options[:time_separator] ||= " : "
|
684
725
|
end
|
685
726
|
|
686
727
|
def select_datetime
|
@@ -750,7 +791,7 @@ module ActionView
|
|
750
791
|
if @options[:use_hidden] || @options[:discard_minute]
|
751
792
|
build_hidden(:minute, min)
|
752
793
|
else
|
753
|
-
build_options_and_select(:minute, min, :
|
794
|
+
build_options_and_select(:minute, min, step: @options[:minute_step])
|
754
795
|
end
|
755
796
|
end
|
756
797
|
|
@@ -770,7 +811,7 @@ module ActionView
|
|
770
811
|
if @options[:use_hidden] || @options[:discard_day]
|
771
812
|
build_hidden(:day, day || 1)
|
772
813
|
else
|
773
|
-
build_options_and_select(:day, day, :
|
814
|
+
build_options_and_select(:day, day, start: 1, end: 31, leading_zeros: false, use_two_digit_numbers: @options[:use_two_digit_numbers])
|
774
815
|
end
|
775
816
|
end
|
776
817
|
|
@@ -780,17 +821,17 @@ module ActionView
|
|
780
821
|
else
|
781
822
|
month_options = []
|
782
823
|
1.upto(12) do |month_number|
|
783
|
-
options = { :
|
824
|
+
options = { value: month_number }
|
784
825
|
options[:selected] = "selected" if month == month_number
|
785
|
-
month_options << content_tag(
|
826
|
+
month_options << content_tag("option", month_name(month_number), options) + "\n"
|
786
827
|
end
|
787
828
|
build_select(:month, month_options.join)
|
788
829
|
end
|
789
830
|
end
|
790
831
|
|
791
832
|
def select_year
|
792
|
-
if
|
793
|
-
val =
|
833
|
+
if !year || @datetime == 0
|
834
|
+
val = "1"
|
794
835
|
middle_year = Date.today.year
|
795
836
|
else
|
796
837
|
val = middle_year = year
|
@@ -810,14 +851,19 @@ module ActionView
|
|
810
851
|
raise ArgumentError, "There are too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter."
|
811
852
|
end
|
812
853
|
|
813
|
-
|
854
|
+
build_select(:year, build_year_options(val, options))
|
814
855
|
end
|
815
856
|
end
|
816
857
|
|
817
858
|
private
|
818
859
|
%w( sec min hour day month year ).each do |method|
|
819
860
|
define_method(method) do
|
820
|
-
|
861
|
+
case @datetime
|
862
|
+
when Hash then @datetime[method.to_sym]
|
863
|
+
when Numeric then @datetime
|
864
|
+
when nil then nil
|
865
|
+
else @datetime.send(method)
|
866
|
+
end
|
821
867
|
end
|
822
868
|
end
|
823
869
|
|
@@ -825,12 +871,12 @@ module ActionView
|
|
825
871
|
# valid. Otherwise, February 31st or February 29th, 2011 can be selected, which are invalid.
|
826
872
|
def set_day_if_discarded
|
827
873
|
if @datetime && @options[:discard_day]
|
828
|
-
@datetime = @datetime.change(:
|
874
|
+
@datetime = @datetime.change(day: 1)
|
829
875
|
end
|
830
876
|
end
|
831
877
|
|
832
878
|
# Returns translated month names, but also ensures that a custom month
|
833
|
-
# name array has a leading nil element.
|
879
|
+
# name array has a leading +nil+ element.
|
834
880
|
def month_names
|
835
881
|
@month_names ||= begin
|
836
882
|
month_names = @options[:use_month_names] || translated_month_names
|
@@ -850,7 +896,7 @@ module ActionView
|
|
850
896
|
# "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
851
897
|
def translated_month_names
|
852
898
|
key = @options[:use_short_month] ? :'date.abbr_month_names' : :'date.month_names'
|
853
|
-
I18n.translate(key, :
|
899
|
+
I18n.translate(key, locale: @options[:locale])
|
854
900
|
end
|
855
901
|
|
856
902
|
# Looks up month names by number (1-based):
|
@@ -878,23 +924,38 @@ module ActionView
|
|
878
924
|
if @options[:use_month_numbers]
|
879
925
|
number
|
880
926
|
elsif @options[:use_two_digit_numbers]
|
881
|
-
|
927
|
+
"%02d" % number
|
882
928
|
elsif @options[:add_month_numbers]
|
883
929
|
"#{number} - #{month_names[number]}"
|
884
930
|
elsif format_string = @options[:month_format_string]
|
885
|
-
format_string % {number: number, name: month_names[number]}
|
931
|
+
format_string % { number: number, name: month_names[number] }
|
886
932
|
else
|
887
933
|
month_names[number]
|
888
934
|
end
|
889
935
|
end
|
890
936
|
|
937
|
+
# Looks up year names by number.
|
938
|
+
#
|
939
|
+
# year_name(1998) # => 1998
|
940
|
+
#
|
941
|
+
# If the <tt>:year_format</tt> option is passed:
|
942
|
+
#
|
943
|
+
# year_name(1998) # => "Heisei 10"
|
944
|
+
def year_name(number)
|
945
|
+
if year_format_lambda = @options[:year_format]
|
946
|
+
year_format_lambda.call(number)
|
947
|
+
else
|
948
|
+
number
|
949
|
+
end
|
950
|
+
end
|
951
|
+
|
891
952
|
def date_order
|
892
953
|
@date_order ||= @options[:order] || translated_date_order
|
893
954
|
end
|
894
955
|
|
895
956
|
def translated_date_order
|
896
|
-
date_order = I18n.translate(:'date.order', :
|
897
|
-
date_order = date_order.map
|
957
|
+
date_order = I18n.translate(:'date.order', locale: @options[:locale], default: [])
|
958
|
+
date_order = date_order.map(&:to_sym)
|
898
959
|
|
899
960
|
forbidden_elements = date_order - [:year, :month, :day]
|
900
961
|
if forbidden_elements.any?
|
@@ -910,7 +971,7 @@ module ActionView
|
|
910
971
|
build_select(type, build_options(selected, options))
|
911
972
|
end
|
912
973
|
|
913
|
-
# Build select option
|
974
|
+
# Build select option HTML from date value and options.
|
914
975
|
# build_options(15, start: 1, end: 31)
|
915
976
|
# => "<option value="1">1</option>
|
916
977
|
# <option value="2">2</option>
|
@@ -940,52 +1001,96 @@ module ActionView
|
|
940
1001
|
select_options = []
|
941
1002
|
start.step(stop, step) do |i|
|
942
1003
|
value = leading_zeros ? sprintf("%02d", i) : i
|
943
|
-
tag_options = { :
|
1004
|
+
tag_options = { value: value }
|
944
1005
|
tag_options[:selected] = "selected" if selected == i
|
945
1006
|
text = options[:use_two_digit_numbers] ? sprintf("%02d", i) : value
|
946
1007
|
text = options[:ampm] ? AMPM_TRANSLATION[i] : text
|
947
|
-
select_options << content_tag(
|
1008
|
+
select_options << content_tag("option", text, tag_options)
|
948
1009
|
end
|
949
1010
|
|
950
1011
|
(select_options.join("\n") + "\n").html_safe
|
951
1012
|
end
|
952
1013
|
|
953
|
-
#
|
1014
|
+
# Build select option HTML for year.
|
1015
|
+
# If <tt>year_format</tt> option is not passed
|
1016
|
+
# build_year_options(1998, start: 1998, end: 2000)
|
1017
|
+
# => "<option value="1998" selected="selected">1998</option>
|
1018
|
+
# <option value="1999">1999</option>
|
1019
|
+
# <option value="2000">2000</option>"
|
1020
|
+
#
|
1021
|
+
# If <tt>year_format</tt> option is passed
|
1022
|
+
# build_year_options(1998, start: 1998, end: 2000, year_format: ->year { "Heisei #{ year - 1988 }" })
|
1023
|
+
# => "<option value="1998" selected="selected">Heisei 10</option>
|
1024
|
+
# <option value="1999">Heisei 11</option>
|
1025
|
+
# <option value="2000">Heisei 12</option>"
|
1026
|
+
def build_year_options(selected, options = {})
|
1027
|
+
start = options.delete(:start)
|
1028
|
+
stop = options.delete(:end)
|
1029
|
+
step = options.delete(:step)
|
1030
|
+
|
1031
|
+
select_options = []
|
1032
|
+
start.step(stop, step) do |value|
|
1033
|
+
tag_options = { value: value }
|
1034
|
+
tag_options[:selected] = "selected" if selected == value
|
1035
|
+
text = year_name(value)
|
1036
|
+
select_options << content_tag("option", text, tag_options)
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
(select_options.join("\n") + "\n").html_safe
|
1040
|
+
end
|
1041
|
+
|
1042
|
+
# Builds select tag from date type and HTML select options.
|
954
1043
|
# build_select(:month, "<option value="1">January</option>...")
|
955
1044
|
# => "<select id="post_written_on_2i" name="post[written_on(2i)]">
|
956
1045
|
# <option value="1">January</option>...
|
957
1046
|
# </select>"
|
958
1047
|
def build_select(type, select_options_as_html)
|
959
1048
|
select_options = {
|
960
|
-
:
|
961
|
-
:
|
1049
|
+
id: input_id_from_type(type),
|
1050
|
+
name: input_name_from_type(type)
|
962
1051
|
}.merge!(@html_options)
|
963
|
-
select_options[:disabled] =
|
964
|
-
select_options[:class] =
|
1052
|
+
select_options[:disabled] = "disabled" if @options[:disabled]
|
1053
|
+
select_options[:class] = css_class_attribute(type, select_options[:class], @options[:with_css_classes]) if @options[:with_css_classes]
|
965
1054
|
|
966
|
-
select_html = "\n"
|
967
|
-
select_html << content_tag(
|
1055
|
+
select_html = +"\n"
|
1056
|
+
select_html << content_tag("option", "", value: "", label: " ") + "\n" if @options[:include_blank]
|
968
1057
|
select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
|
969
1058
|
select_html << select_options_as_html
|
970
1059
|
|
971
|
-
(content_tag(
|
1060
|
+
(content_tag("select", select_html.html_safe, select_options) + "\n").html_safe
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
# Builds the css class value for the select element
|
1064
|
+
# css_class_attribute(:year, 'date optional', { year: 'my-year' })
|
1065
|
+
# => "date optional my-year"
|
1066
|
+
def css_class_attribute(type, html_options_class, options) # :nodoc:
|
1067
|
+
css_class = \
|
1068
|
+
case options
|
1069
|
+
when Hash
|
1070
|
+
options[type.to_sym]
|
1071
|
+
else
|
1072
|
+
type
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
[html_options_class, css_class].compact.join(" ")
|
972
1076
|
end
|
973
1077
|
|
974
1078
|
# Builds a prompt option tag with supplied options or from default options.
|
975
1079
|
# prompt_option_tag(:month, prompt: 'Select month')
|
976
1080
|
# => "<option value="">Select month</option>"
|
977
1081
|
def prompt_option_tag(type, options)
|
978
|
-
prompt =
|
1082
|
+
prompt = \
|
1083
|
+
case options
|
979
1084
|
when Hash
|
980
|
-
default_options = {:
|
1085
|
+
default_options = { year: false, month: false, day: false, hour: false, minute: false, second: false }
|
981
1086
|
default_options.merge!(options)[type.to_sym]
|
982
1087
|
when String
|
983
1088
|
options
|
984
1089
|
else
|
985
|
-
I18n.translate(:"datetime.prompts.#{type}", :
|
986
|
-
|
1090
|
+
I18n.translate(:"datetime.prompts.#{type}", locale: @options[:locale])
|
1091
|
+
end
|
987
1092
|
|
988
|
-
prompt ? content_tag(
|
1093
|
+
prompt ? content_tag("option", prompt, value: "") : ""
|
989
1094
|
end
|
990
1095
|
|
991
1096
|
# Builds hidden input tag for date part and value.
|
@@ -993,12 +1098,12 @@ module ActionView
|
|
993
1098
|
# => "<input id="post_written_on_1i" name="post[written_on(1i)]" type="hidden" value="2008" />"
|
994
1099
|
def build_hidden(type, value)
|
995
1100
|
select_options = {
|
996
|
-
:
|
997
|
-
:
|
998
|
-
:
|
999
|
-
:
|
1101
|
+
type: "hidden",
|
1102
|
+
id: input_id_from_type(type),
|
1103
|
+
name: input_name_from_type(type),
|
1104
|
+
value: value
|
1000
1105
|
}.merge!(@html_options.slice(:disabled))
|
1001
|
-
select_options[:disabled] =
|
1106
|
+
select_options[:disabled] = "disabled" if @options[:disabled]
|
1002
1107
|
|
1003
1108
|
tag(:input, select_options) + "\n".html_safe
|
1004
1109
|
end
|
@@ -1009,7 +1114,7 @@ module ActionView
|
|
1009
1114
|
prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
|
1010
1115
|
prefix += "[#{@options[:index]}]" if @options.has_key?(:index)
|
1011
1116
|
|
1012
|
-
field_name = @options[:field_name] || type
|
1117
|
+
field_name = @options[:field_name] || type.to_s
|
1013
1118
|
if @options[:include_position]
|
1014
1119
|
field_name += "(#{ActionView::Helpers::DateTimeSelector::POSITION[type]}i)"
|
1015
1120
|
end
|
@@ -1020,8 +1125,8 @@ module ActionView
|
|
1020
1125
|
# Returns the id attribute for the input tag.
|
1021
1126
|
# => "post_written_on_1i"
|
1022
1127
|
def input_id_from_type(type)
|
1023
|
-
id = input_name_from_type(type).gsub(/([\[\(])|(\]\[)/,
|
1024
|
-
id = @options[:namespace] +
|
1128
|
+
id = input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, "_").gsub(/[\]\)]/, "")
|
1129
|
+
id = @options[:namespace] + "_" + id if @options[:namespace]
|
1025
1130
|
|
1026
1131
|
id
|
1027
1132
|
end
|
@@ -1029,11 +1134,11 @@ module ActionView
|
|
1029
1134
|
# Given an ordering of datetime components, create the selection HTML
|
1030
1135
|
# and join them with their appropriate separators.
|
1031
1136
|
def build_selects_from_types(order)
|
1032
|
-
select =
|
1137
|
+
select = +""
|
1033
1138
|
first_visible = order.find { |type| !@options[:"discard_#{type}"] }
|
1034
|
-
order.
|
1139
|
+
order.reverse_each do |type|
|
1035
1140
|
separator = separator(type) unless type == first_visible # don't add before first visible field
|
1036
|
-
select.insert(0, separator.to_s +
|
1141
|
+
select.insert(0, separator.to_s + public_send("select_#{type}").to_s)
|
1037
1142
|
end
|
1038
1143
|
select.html_safe
|
1039
1144
|
end
|
@@ -1043,12 +1148,12 @@ module ActionView
|
|
1043
1148
|
return "" if @options[:use_hidden]
|
1044
1149
|
|
1045
1150
|
case type
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1151
|
+
when :year, :month, :day
|
1152
|
+
@options[:"discard_#{type}"] ? "" : @options[:date_separator]
|
1153
|
+
when :hour
|
1154
|
+
(@options[:discard_year] && @options[:discard_day]) ? "" : @options[:datetime_separator]
|
1155
|
+
when :minute, :second
|
1156
|
+
@options[:"discard_#{type}"] ? "" : @options[:time_separator]
|
1052
1157
|
end
|
1053
1158
|
end
|
1054
1159
|
end
|