simple_form 2.1.0 → 3.2.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.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +77 -33
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +387 -187
  5. data/lib/generators/simple_form/install_generator.rb +4 -4
  6. data/lib/generators/simple_form/templates/README +3 -4
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +45 -22
  8. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +128 -24
  9. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +87 -6
  10. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
  11. data/lib/simple_form/action_view_extensions/builder.rb +2 -319
  12. data/lib/simple_form/action_view_extensions/form_helper.rb +8 -11
  13. data/lib/simple_form/components/errors.rb +28 -2
  14. data/lib/simple_form/components/hints.rb +8 -3
  15. data/lib/simple_form/components/html5.rb +6 -3
  16. data/lib/simple_form/components/label_input.rb +20 -2
  17. data/lib/simple_form/components/labels.rb +14 -10
  18. data/lib/simple_form/components/maxlength.rb +2 -9
  19. data/lib/simple_form/components/min_max.rb +1 -1
  20. data/lib/simple_form/components/pattern.rb +3 -3
  21. data/lib/simple_form/components/placeholders.rb +2 -2
  22. data/lib/simple_form/components/readonly.rb +1 -1
  23. data/lib/simple_form/components.rb +1 -1
  24. data/lib/simple_form/error_notification.rb +2 -2
  25. data/lib/simple_form/form_builder.rb +262 -107
  26. data/lib/simple_form/helpers.rb +6 -6
  27. data/lib/simple_form/inputs/base.rb +37 -16
  28. data/lib/simple_form/inputs/block_input.rb +2 -2
  29. data/lib/simple_form/inputs/boolean_input.rb +33 -18
  30. data/lib/simple_form/inputs/collection_input.rb +34 -13
  31. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +7 -12
  32. data/lib/simple_form/inputs/collection_select_input.rb +4 -2
  33. data/lib/simple_form/inputs/date_time_input.rb +23 -9
  34. data/lib/simple_form/inputs/file_input.rb +4 -2
  35. data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
  36. data/lib/simple_form/inputs/hidden_input.rb +4 -2
  37. data/lib/simple_form/inputs/numeric_input.rb +3 -8
  38. data/lib/simple_form/inputs/password_input.rb +4 -3
  39. data/lib/simple_form/inputs/priority_input.rb +4 -2
  40. data/lib/simple_form/inputs/range_input.rb +1 -1
  41. data/lib/simple_form/inputs/string_input.rb +4 -3
  42. data/lib/simple_form/inputs/text_input.rb +4 -2
  43. data/lib/simple_form/railtie.rb +14 -0
  44. data/lib/simple_form/tags.rb +68 -0
  45. data/lib/simple_form/version.rb +1 -1
  46. data/lib/simple_form/wrappers/builder.rb +11 -35
  47. data/lib/simple_form/wrappers/leaf.rb +28 -0
  48. data/lib/simple_form/wrappers/many.rb +7 -7
  49. data/lib/simple_form/wrappers/root.rb +2 -2
  50. data/lib/simple_form/wrappers/single.rb +5 -3
  51. data/lib/simple_form/wrappers.rb +2 -1
  52. data/lib/simple_form.rb +99 -52
  53. data/test/action_view_extensions/builder_test.rb +113 -127
  54. data/test/action_view_extensions/form_helper_test.rb +58 -30
  55. data/test/components/label_test.rb +83 -83
  56. data/test/form_builder/association_test.rb +96 -61
  57. data/test/form_builder/button_test.rb +14 -14
  58. data/test/form_builder/error_notification_test.rb +9 -9
  59. data/test/form_builder/error_test.rb +159 -34
  60. data/test/form_builder/general_test.rb +176 -121
  61. data/test/form_builder/hint_test.rb +43 -37
  62. data/test/form_builder/input_field_test.rb +99 -52
  63. data/test/form_builder/label_test.rb +67 -15
  64. data/test/form_builder/wrapper_test.rb +157 -41
  65. data/test/generators/simple_form_generator_test.rb +4 -4
  66. data/test/inputs/boolean_input_test.rb +92 -24
  67. data/test/inputs/collection_check_boxes_input_test.rb +150 -71
  68. data/test/inputs/collection_radio_buttons_input_test.rb +213 -113
  69. data/test/inputs/collection_select_input_test.rb +221 -85
  70. data/test/inputs/datetime_input_test.rb +125 -47
  71. data/test/inputs/disabled_test.rb +25 -25
  72. data/test/inputs/discovery_test.rb +60 -10
  73. data/test/inputs/file_input_test.rb +3 -3
  74. data/test/inputs/general_test.rb +48 -32
  75. data/test/inputs/grouped_collection_select_input_test.rb +76 -27
  76. data/test/inputs/hidden_input_test.rb +6 -5
  77. data/test/inputs/numeric_input_test.rb +46 -46
  78. data/test/inputs/priority_input_test.rb +21 -15
  79. data/test/inputs/readonly_test.rb +31 -31
  80. data/test/inputs/required_test.rb +30 -18
  81. data/test/inputs/string_input_test.rb +53 -52
  82. data/test/inputs/text_input_test.rb +15 -8
  83. data/test/simple_form_test.rb +8 -0
  84. data/test/support/discovery_inputs.rb +32 -2
  85. data/test/support/misc_helpers.rb +130 -29
  86. data/test/support/mock_controller.rb +6 -6
  87. data/test/support/models.rb +125 -71
  88. data/test/test_helper.rb +28 -35
  89. metadata +17 -29
  90. data/lib/simple_form/action_view_extensions/builder.rb.orig +0 -247
  91. data/lib/simple_form/core_ext/hash.rb +0 -16
  92. data/lib/simple_form/form_builder.rb.orig +0 -486
  93. data/lib/simple_form/version.rb.orig +0 -7
@@ -1,187 +1,8 @@
1
1
  module SimpleForm
2
2
  module ActionViewExtensions
3
- # Base builder to handle each instance of a collection of radio buttons / check boxes.
4
- # Based on (at this time upcoming) Rails 4 collection builders.
5
- class BuilderBase #:nodoc:
6
- attr_reader :object, :text, :value
7
-
8
- def initialize(form_builder, method_name, object, sanitized_attribute_name, text,
9
- value, input_html_options)
10
- @form_builder = form_builder
11
- @method_name = method_name
12
- @object = object
13
- @sanitized_attribute_name = sanitized_attribute_name
14
- @text = text
15
- @value = value
16
- @input_html_options = input_html_options
17
- end
18
-
19
- def label(label_html_options={}, &block)
20
- @form_builder.label(@sanitized_attribute_name, @text, label_html_options, &block)
21
- end
22
- end
23
-
24
- # Handles generating an instance of radio + label for collection_radio_buttons.
25
- class RadioButtonBuilder < BuilderBase #:nodoc:
26
- def radio_button(extra_html_options={})
27
- html_options = extra_html_options.merge(@input_html_options)
28
- @form_builder.radio_button(@method_name, @value, html_options)
29
- end
30
- end
31
-
32
- # Handles generating an instance of check box + label for collection_check_boxes.
33
- class CheckBoxBuilder < BuilderBase #:nodoc:
34
- def check_box(extra_html_options={})
35
- html_options = extra_html_options.merge(@input_html_options)
36
- @form_builder.check_box(@method_name, html_options, @value, nil)
37
- end
38
- end
39
-
40
3
  # A collection of methods required by simple_form but added to rails default form.
41
4
  # This means that you can use such methods outside simple_form context.
42
5
  module Builder
43
- # Create a collection of radio inputs for the attribute. Basically this
44
- # helper will create a radio input associated with a label for each
45
- # text/value option in the collection, using value_method and text_method
46
- # to convert these text/value. You can give a symbol or a proc to both
47
- # value_method and text_method, that will be evaluated for each item in
48
- # the collection.
49
- #
50
- # == Examples
51
- #
52
- # form_for @user do |f|
53
- # f.collection_radio_buttons :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
54
- # end
55
- #
56
- # <input id="user_options_true" name="user[options]" type="radio" value="true" />
57
- # <label class="collection_radio_buttons" for="user_options_true">Yes</label>
58
- # <input id="user_options_false" name="user[options]" type="radio" value="false" />
59
- # <label class="collection_radio_buttons" for="user_options_false">No</label>
60
- #
61
- # It is also possible to give a block that should generate the radio +
62
- # label. To wrap the radio with the label, for instance:
63
- #
64
- # form_for @user do |f|
65
- # f.collection_radio_buttons(
66
- # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
67
- # ) do |b|
68
- # b.label { b.radio_button + b.text }
69
- # end
70
- # end
71
- #
72
- # == Options
73
- #
74
- # Collection radio accepts some extra options:
75
- #
76
- # * checked => the value that should be checked initially.
77
- #
78
- # * disabled => the value or values that should be disabled. Accepts a single
79
- # item or an array of items.
80
- #
81
- # * collection_wrapper_tag => the tag to wrap the entire collection.
82
- #
83
- # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
84
- #
85
- # * item_wrapper_tag => the tag to wrap each item in the collection.
86
- #
87
- # * item_wrapper_class => the CSS class to use for item_wrapper_tag
88
- #
89
- # * a block => to generate the label + radio or any other component.
90
- #
91
- def collection_radio_buttons(attribute, collection, value_method, text_method, options={}, html_options={})
92
- rendered_collection = render_collection(
93
- collection, value_method, text_method, options, html_options
94
- ) do |item, value, text, default_html_options|
95
- builder = instantiate_collection_builder(RadioButtonBuilder, attribute, item, value, text, default_html_options)
96
-
97
- if block_given?
98
- yield builder
99
- else
100
- builder.radio_button + builder.label(:class => "collection_radio_buttons")
101
- end
102
- end
103
-
104
- wrap_rendered_collection(rendered_collection, options)
105
- end
106
-
107
- # deprecated
108
- def collection_radio(*args, &block)
109
- SimpleForm.deprecation_warn "The `collection_radio` helper is deprecated, " \
110
- "please use `collection_radio_buttons` instead."
111
- collection_radio_buttons(*args, &block)
112
- end
113
-
114
- # Creates a collection of check boxes for each item in the collection,
115
- # associated with a clickable label. Use value_method and text_method to
116
- # convert items in the collection for use as text/value in check boxes.
117
- # You can give a symbol or a proc to both value_method and text_method,
118
- # that will be evaluated for each item in the collection.
119
- #
120
- # == Examples
121
- #
122
- # form_for @user do |f|
123
- # f.collection_check_boxes :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
124
- # end
125
- #
126
- # <input name="user[options][]" type="hidden" value="" />
127
- # <input id="user_options_true" name="user[options][]" type="checkbox" value="true" />
128
- # <label class="collection_check_boxes" for="user_options_true">Yes</label>
129
- # <input name="user[options][]" type="hidden" value="" />
130
- # <input id="user_options_false" name="user[options][]" type="checkbox" value="false" />
131
- # <label class="collection_check_boxes" for="user_options_false">No</label>
132
- #
133
- # It is also possible to give a block that should generate the check box +
134
- # label. To wrap the check box with the label, for instance:
135
- #
136
- # form_for @user do |f|
137
- # f.collection_check_boxes(
138
- # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
139
- # ) do |b|
140
- # b.label { b.check_box + b.text }
141
- # end
142
- # end
143
- #
144
- # == Options
145
- #
146
- # Collection check box accepts some extra options:
147
- #
148
- # * checked => the value or values that should be checked initially. Accepts
149
- # a single item or an array of items. It overrides existing associations.
150
- #
151
- # * disabled => the value or values that should be disabled. Accepts a single
152
- # item or an array of items.
153
- #
154
- # * collection_wrapper_tag => the tag to wrap the entire collection.
155
- #
156
- # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag. This option
157
- # is ignored if the :collection_wrapper_tag option is blank.
158
- #
159
- # * item_wrapper_tag => the tag to wrap each item in the collection.
160
- #
161
- # * item_wrapper_class => the CSS class to use for item_wrapper_tag
162
- #
163
- # * a block => to generate the label + check box or any other component.
164
- #
165
- def collection_check_boxes(attribute, collection, value_method, text_method, options={}, html_options={})
166
- rendered_collection = render_collection(
167
- collection, value_method, text_method, options, html_options
168
- ) do |item, value, text, default_html_options|
169
- default_html_options[:multiple] = true
170
- builder = instantiate_collection_builder(CheckBoxBuilder, attribute, item, value, text, default_html_options)
171
-
172
- if block_given?
173
- yield builder
174
- else
175
- builder.check_box + builder.label(:class => "collection_check_boxes")
176
- end
177
- end
178
-
179
- # Append a hidden field to make sure something will be sent back to the
180
- # server if all checkboxes are unchecked.
181
- hidden = @template.hidden_field_tag("#{object_name}[#{attribute}][]", "", :id => nil)
182
-
183
- wrap_rendered_collection(rendered_collection + hidden, options)
184
- end
185
6
 
186
7
  # Wrapper for using SimpleForm inside a default rails form.
187
8
  # Example:
@@ -196,79 +17,14 @@ module SimpleForm
196
17
  options = args.extract_options!
197
18
  options[:wrapper] = self.options[:wrapper] if options[:wrapper].nil?
198
19
  options[:defaults] ||= self.options[:defaults]
20
+ options[:wrapper_mappings] ||= self.options[:wrapper_mappings]
199
21
 
200
22
  if self.class < ActionView::Helpers::FormBuilder
201
23
  options[:builder] ||= self.class
202
24
  else
203
25
  options[:builder] ||= SimpleForm::FormBuilder
204
26
  end
205
- fields_for(*(args << options), &block)
206
- end
207
-
208
- private
209
-
210
- def instantiate_collection_builder(builder_class, attribute, item, value, text, html_options)
211
- builder_class.new(self, attribute, item,
212
- sanitize_attribute_name(attribute, value), text, value, html_options)
213
- end
214
-
215
- # Generate default options for collection helpers, such as :checked and
216
- # :disabled.
217
- def default_html_options_for_collection(item, value, options, html_options) #:nodoc:
218
- html_options = html_options.dup
219
-
220
- [:checked, :selected, :disabled].each do |option|
221
- current_option = options[option]
222
- next if current_option.nil?
223
-
224
- accept = if current_option.respond_to?(:call)
225
- current_option.call(item)
226
- else
227
- Array(current_option).map(&:to_s).include?(value.to_s)
228
- end
229
-
230
- if accept
231
- html_options[option] = true
232
- elsif option == :checked
233
- html_options[option] = false
234
- end
235
- end
236
-
237
- html_options
238
- end
239
-
240
- def sanitize_attribute_name(attribute, value) #:nodoc:
241
- "#{attribute}_#{value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase}"
242
- end
243
-
244
- def render_collection(collection, value_method, text_method, options={}, html_options={}) #:nodoc:
245
- item_wrapper_tag = options.fetch(:item_wrapper_tag, :span)
246
- item_wrapper_class = options[:item_wrapper_class]
247
-
248
- collection.map do |item|
249
- value = value_for_collection(item, value_method)
250
- text = value_for_collection(item, text_method)
251
- default_html_options = default_html_options_for_collection(item, value, options, html_options)
252
-
253
- rendered_item = yield item, value, text, default_html_options
254
-
255
- item_wrapper_tag ? @template.content_tag(item_wrapper_tag, rendered_item, :class => item_wrapper_class) : rendered_item
256
- end.join.html_safe
257
- end
258
-
259
- def value_for_collection(item, value) #:nodoc:
260
- value.respond_to?(:call) ? value.call(item) : item.send(value)
261
- end
262
-
263
- def wrap_rendered_collection(collection, options)
264
- wrapper_tag = options[:collection_wrapper_tag]
265
-
266
- if wrapper_tag
267
- wrapper_class = options[:collection_wrapper_class]
268
- @template.content_tag(wrapper_tag, collection, :class => wrapper_class)
269
- else
270
- collection
271
- end
27
+ fields_for(*args, options, &block)
272
28
  end
273
29
  end
274
30
  end
@@ -278,77 +34,4 @@ module ActionView::Helpers
278
34
  class FormBuilder
279
35
  include SimpleForm::ActionViewExtensions::Builder
280
36
  end
281
-
282
- module FormOptionsHelper
283
- # Override Rails options_from_collection_for_select to handle lambdas/procs in
284
- # text and value methods, so it works the same way as collection_radio_buttons
285
- # and collection_check_boxes in SimpleForm. If none of text/value methods is a
286
- # callable object, then it just delegates back to original collection select.
287
- # FIXME: remove when support only Rails 4.0 forward
288
- # https://github.com/rails/rails/commit/9035324367526af0300477a58b6d3efc15d1a5a8
289
- alias :original_options_from_collection_for_select :options_from_collection_for_select
290
- def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
291
- if value_method.respond_to?(:call) || text_method.respond_to?(:call)
292
- collection = collection.map do |item|
293
- value = value_for_collection(item, value_method)
294
- text = value_for_collection(item, text_method)
295
-
296
- [value, text]
297
- end
298
-
299
- value_method, text_method = :first, :last
300
- selected = extract_selected_and_disabled_and_call_procs selected, collection
301
- end
302
-
303
- original_options_from_collection_for_select collection, value_method, text_method, selected
304
- end
305
-
306
- private
307
-
308
- def extract_selected_and_disabled_and_call_procs(selected, collection)
309
- selected, disabled = extract_selected_and_disabled selected
310
- selected_disabled = { :selected => selected, :disabled => disabled }
311
-
312
- selected_disabled.each do |key, check|
313
- if check.is_a? Proc
314
- values = collection.map { |option| option.first if check.call(option.first) }
315
- selected_disabled[key] = values
316
- end
317
- end
318
- end
319
-
320
- def value_for_collection(item, value) #:nodoc:
321
- value.respond_to?(:call) ? value.call(item) : item.send(value)
322
- end
323
- end
324
-
325
- # Backport Rails fix to checkbox tag element, which does not generate the
326
- # hidden input when given nil as unchecked value. This is to make SimpleForm
327
- # collection check boxes helper to work fine with nested boolean style, when
328
- # they are wrapped in labels. Without that, clicking in the label would
329
- # actually change the hidden input, instead of the checkbox.
330
- # FIXME: remove when support only Rails >= 3.2.2.
331
- class InstanceTag
332
- def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
333
- options = options.stringify_keys
334
- options["type"] = "checkbox"
335
- options["value"] = checked_value
336
- if options.has_key?("checked")
337
- cv = options.delete "checked"
338
- checked = cv == true || cv == "checked"
339
- else
340
- checked = self.class.check_box_checked?(value(object), checked_value)
341
- end
342
- options["checked"] = "checked" if checked
343
- if options["multiple"]
344
- add_default_name_and_id_for_value(checked_value, options)
345
- options.delete("multiple")
346
- else
347
- add_default_name_and_id(options)
348
- end
349
- hidden = unchecked_value ? tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value, "disabled" => options["disabled"]) : "".html_safe
350
- checkbox = tag("input", options)
351
- hidden + checkbox
352
- end
353
- end
354
37
  end
@@ -5,25 +5,22 @@ module SimpleForm
5
5
  # Example:
6
6
  #
7
7
  # simple_form_for @user do |f|
8
- # f.input :name, :hint => 'My hint'
8
+ # f.input :name, hint: 'My hint'
9
9
  # end
10
10
  #
11
11
  module FormHelper
12
- # Override the default ActiveRecordHelper behaviour of wrapping the input.
13
- # This gets taken care of semantically by adding an error class to the wrapper tag
14
- # containing the input.
15
- #
16
- FIELD_ERROR_PROC = proc do |html_tag, instance_tag|
17
- html_tag
18
- end
19
12
 
20
- def simple_form_for(record, options={}, &block)
13
+ def simple_form_for(record, options = {}, &block)
21
14
  options[:builder] ||= SimpleForm::FormBuilder
22
15
  options[:html] ||= {}
23
16
  unless options[:html].key?(:novalidate)
24
17
  options[:html][:novalidate] = !SimpleForm.browser_validations
25
18
  end
26
- options[:html][:class] = [SimpleForm.form_class, simple_form_css_class(record, options)].compact.join(" ")
19
+ if options[:html].key?(:class)
20
+ options[:html][:class] = [SimpleForm.form_class, options[:html][:class]].compact
21
+ else
22
+ options[:html][:class] = [SimpleForm.form_class, SimpleForm.default_form_class, simple_form_css_class(record, options)].compact
23
+ end
27
24
 
28
25
  with_simple_form_field_error_proc do
29
26
  form_for(record, options, &block)
@@ -44,7 +41,7 @@ module SimpleForm
44
41
  def with_simple_form_field_error_proc
45
42
  default_field_error_proc = ::ActionView::Base.field_error_proc
46
43
  begin
47
- ::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
44
+ ::ActionView::Base.field_error_proc = SimpleForm.field_error_proc
48
45
  yield
49
46
  ensure
50
47
  ::ActionView::Base.field_error_proc = default_field_error_proc
@@ -1,10 +1,14 @@
1
1
  module SimpleForm
2
2
  module Components
3
3
  module Errors
4
- def error
4
+ def error(wrapper_options = nil)
5
5
  error_text if has_errors?
6
6
  end
7
7
 
8
+ def full_error(wrapper_options = nil)
9
+ full_error_text if options[:error] != false && has_errors?
10
+ end
11
+
8
12
  def has_errors?
9
13
  object && object.respond_to?(:errors) && errors.present?
10
14
  end
@@ -12,7 +16,13 @@ module SimpleForm
12
16
  protected
13
17
 
14
18
  def error_text
15
- "#{options[:error_prefix]} #{errors.send(error_method)}".lstrip.html_safe
19
+ text = has_custom_error? ? options[:error] : errors.send(error_method)
20
+
21
+ "#{html_escape(options[:error_prefix])} #{html_escape(text)}".lstrip.html_safe
22
+ end
23
+
24
+ def full_error_text
25
+ has_custom_error? ? options[:error] : full_errors.send(error_method)
16
26
  end
17
27
 
18
28
  def error_method
@@ -23,13 +33,29 @@ module SimpleForm
23
33
  @errors ||= (errors_on_attribute + errors_on_association).compact
24
34
  end
25
35
 
36
+ def full_errors
37
+ @full_errors ||= (full_errors_on_attribute + full_errors_on_association).compact
38
+ end
39
+
26
40
  def errors_on_attribute
27
41
  object.errors[attribute_name]
28
42
  end
29
43
 
44
+ def full_errors_on_attribute
45
+ object.errors.full_messages_for(attribute_name)
46
+ end
47
+
30
48
  def errors_on_association
31
49
  reflection ? object.errors[reflection.name] : []
32
50
  end
51
+
52
+ def full_errors_on_association
53
+ reflection ? object.errors.full_messages_for(reflection.name) : []
54
+ end
55
+
56
+ def has_custom_error?
57
+ options[:error].is_a?(String)
58
+ end
33
59
  end
34
60
  end
35
61
  end
@@ -2,11 +2,16 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Hints
5
- def hint
5
+ def hint(wrapper_options = nil)
6
6
  @hint ||= begin
7
7
  hint = options[:hint]
8
- hint_content = hint.is_a?(String) ? hint : translate(:hints)
9
- hint_content.html_safe if hint_content
8
+
9
+ if hint.is_a?(String)
10
+ html_escape(hint)
11
+ else
12
+ content = translate_from_namespace(:hints)
13
+ content.html_safe if content
14
+ end
10
15
  end
11
16
  end
12
17
 
@@ -5,9 +5,12 @@ module SimpleForm
5
5
  @html5 = false
6
6
  end
7
7
 
8
- def html5
8
+ def html5(wrapper_options = nil)
9
9
  @html5 = true
10
- input_html_options[:required] = true if has_required?
10
+
11
+ input_html_options[:required] = has_required?
12
+ input_html_options[:'aria-required'] = has_required? || nil
13
+
11
14
  nil
12
15
  end
13
16
 
@@ -23,4 +26,4 @@ module SimpleForm
23
26
  end
24
27
  end
25
28
  end
26
- end
29
+ end
@@ -7,8 +7,26 @@ module SimpleForm
7
7
  include SimpleForm::Components::Labels
8
8
  end
9
9
 
10
- def label_input
11
- options[:label] == false ? input : (label + input)
10
+ def label_input(wrapper_options = nil)
11
+ if options[:label] == false
12
+ deprecated_component(:input, wrapper_options)
13
+ else
14
+ deprecated_component(:label, wrapper_options) + deprecated_component(:input, wrapper_options)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def deprecated_component(namespace, wrapper_options)
21
+ method = method(namespace)
22
+
23
+ if method.arity == 0
24
+ ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: namespace })
25
+
26
+ method.call
27
+ else
28
+ method.call(wrapper_options)
29
+ end
12
30
  end
13
31
  end
14
32
  end
@@ -6,31 +6,34 @@ module SimpleForm
6
6
  module ClassMethods #:nodoc:
7
7
  def translate_required_html
8
8
  i18n_cache :translate_required_html do
9
- I18n.t(:"simple_form.required.html", :default =>
9
+ I18n.t(:"simple_form.required.html", default:
10
10
  %[<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>]
11
11
  )
12
12
  end
13
13
  end
14
14
 
15
15
  def translate_required_text
16
- I18n.t(:"simple_form.required.text", :default => 'required')
16
+ I18n.t(:"simple_form.required.text", default: 'required')
17
17
  end
18
18
 
19
19
  def translate_required_mark
20
- I18n.t(:"simple_form.required.mark", :default => '*')
20
+ I18n.t(:"simple_form.required.mark", default: '*')
21
21
  end
22
22
  end
23
23
 
24
- def label
24
+ def label(wrapper_options = nil)
25
+ label_options = merge_wrapper_options(label_html_options, wrapper_options)
26
+
25
27
  if generate_label_for_attribute?
26
- @builder.label(label_target, label_text, label_html_options)
28
+ @builder.label(label_target, label_text, label_options)
27
29
  else
28
- template.label_tag(nil, label_text, label_html_options)
30
+ template.label_tag(nil, label_text, label_options)
29
31
  end
30
32
  end
31
33
 
32
- def label_text
33
- SimpleForm.label_text.call(raw_label_text, required_label_text).strip.html_safe
34
+ def label_text(wrapper_options = nil)
35
+ label_text = options[:label_text] || SimpleForm.label_text
36
+ label_text.call(html_escape(raw_label_text), required_label_text, options[:label].present?).strip.html_safe
34
37
  end
35
38
 
36
39
  def label_target
@@ -39,13 +42,14 @@ module SimpleForm
39
42
 
40
43
  def label_html_options
41
44
  label_html_classes = SimpleForm.additional_classes_for(:label) {
42
- [input_type, required_class, SimpleForm.label_class].compact
45
+ [input_type, required_class, disabled_class, SimpleForm.label_class].compact
43
46
  }
44
47
 
45
48
  label_options = html_options_for(:label, label_html_classes)
46
49
  if options.key?(:input_html) && options[:input_html].key?(:id)
47
50
  label_options[:for] = options[:input_html][:id]
48
51
  end
52
+
49
53
  label_options
50
54
  end
51
55
 
@@ -62,7 +66,7 @@ module SimpleForm
62
66
 
63
67
  # First check labels translation and then human attribute name.
64
68
  def label_translation #:nodoc:
65
- if SimpleForm.translate_labels && (translated_label = translate(:labels))
69
+ if SimpleForm.translate_labels && (translated_label = translate_from_namespace(:labels))
66
70
  translated_label
67
71
  elsif object.class.respond_to?(:human_attribute_name)
68
72
  object.class.human_attribute_name(reflection_or_attribute_name.to_s)
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Maxlength
5
- def maxlength
5
+ def maxlength(wrapper_options = nil)
6
6
  input_html_options[:maxlength] ||= maximum_length_from_validation || limit
7
7
  nil
8
8
  end
@@ -27,14 +27,7 @@ module SimpleForm
27
27
  end
28
28
 
29
29
  def has_tokenizer?(length_validator)
30
- tokenizer = length_validator.options[:tokenizer]
31
-
32
- # TODO: Remove this check when we drop Rails 3.0 support
33
- if ActiveModel::Validations::LengthValidator.const_defined?(:DEFAULT_TOKENIZER)
34
- tokenizer && tokenizer != ActiveModel::Validations::LengthValidator::DEFAULT_TOKENIZER
35
- else
36
- tokenizer
37
- end
30
+ length_validator.options[:tokenizer]
38
31
  end
39
32
  end
40
33
  end
@@ -1,7 +1,7 @@
1
1
  module SimpleForm
2
2
  module Components
3
3
  module MinMax
4
- def min_max
4
+ def min_max(wrapper_options = nil)
5
5
  if numeric_validator = find_numericality_validator
6
6
  validator_options = numeric_validator.options
7
7
  input_html_options[:min] ||= minimum_value(validator_options)
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Pattern
5
- def pattern
5
+ def pattern(wrapper_options = nil)
6
6
  input_html_options[:pattern] ||= pattern_source
7
7
  nil
8
8
  end
@@ -13,8 +13,8 @@ module SimpleForm
13
13
  pattern = options[:pattern]
14
14
  if pattern.is_a?(String)
15
15
  pattern
16
- elsif pattern_validator = find_pattern_validator
17
- evaluate_format_validator_option(pattern_validator.options[:with]).source
16
+ elsif (pattern_validator = find_pattern_validator) && (with = pattern_validator.options[:with])
17
+ evaluate_format_validator_option(with).source
18
18
  end
19
19
  end
20
20
 
@@ -2,14 +2,14 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Placeholders
5
- def placeholder
5
+ def placeholder(wrapper_options = nil)
6
6
  input_html_options[:placeholder] ||= placeholder_text
7
7
  nil
8
8
  end
9
9
 
10
10
  def placeholder_text
11
11
  placeholder = options[:placeholder]
12
- placeholder.is_a?(String) ? placeholder : translate(:placeholders)
12
+ placeholder.is_a?(String) ? placeholder : translate_from_namespace(:placeholders)
13
13
  end
14
14
  end
15
15
  end
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Readonly
5
- def readonly
5
+ def readonly(wrapper_options = nil)
6
6
  if readonly_attribute? && !has_readonly?
7
7
  input_html_options[:readonly] ||= true
8
8
  input_html_classes << :readonly
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  # Components are a special type of helpers that can work on their own.
3
3
  # For example, by using a component, it will automatically change the
4
4
  # output under given circumstances without user input. For example,
5
- # the disabled helper always need a :disabled => true option given
5
+ # the disabled helper always need a disabled: true option given
6
6
  # to the input in order to be enabled. On the other hand, things like
7
7
  # hints can generate output automatically by doing I18n lookups.
8
8
  module Components