simple_form 3.0.0 → 3.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -22
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +204 -81
  5. data/lib/generators/simple_form/install_generator.rb +3 -3
  6. data/lib/generators/simple_form/templates/README +3 -4
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +28 -7
  8. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +115 -24
  9. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +86 -5
  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 +1 -0
  12. data/lib/simple_form/action_view_extensions/form_helper.rb +6 -2
  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 +1 -1
  16. data/lib/simple_form/components/label_input.rb +20 -2
  17. data/lib/simple_form/components/labels.rb +10 -6
  18. data/lib/simple_form/components/maxlength.rb +1 -1
  19. data/lib/simple_form/components/min_max.rb +1 -1
  20. data/lib/simple_form/components/pattern.rb +1 -1
  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/form_builder.rb +123 -73
  24. data/lib/simple_form/helpers.rb +5 -5
  25. data/lib/simple_form/inputs/base.rb +36 -11
  26. data/lib/simple_form/inputs/block_input.rb +1 -1
  27. data/lib/simple_form/inputs/boolean_input.rb +28 -15
  28. data/lib/simple_form/inputs/collection_input.rb +30 -9
  29. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +6 -11
  30. data/lib/simple_form/inputs/collection_select_input.rb +4 -2
  31. data/lib/simple_form/inputs/date_time_input.rb +12 -2
  32. data/lib/simple_form/inputs/file_input.rb +4 -2
  33. data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
  34. data/lib/simple_form/inputs/hidden_input.rb +4 -2
  35. data/lib/simple_form/inputs/numeric_input.rb +5 -4
  36. data/lib/simple_form/inputs/password_input.rb +4 -2
  37. data/lib/simple_form/inputs/priority_input.rb +4 -2
  38. data/lib/simple_form/inputs/range_input.rb +1 -1
  39. data/lib/simple_form/inputs/string_input.rb +4 -2
  40. data/lib/simple_form/inputs/text_input.rb +4 -2
  41. data/lib/simple_form/railtie.rb +7 -0
  42. data/lib/simple_form/tags.rb +6 -0
  43. data/lib/simple_form/version.rb +1 -1
  44. data/lib/simple_form/wrappers/builder.rb +6 -6
  45. data/lib/simple_form/wrappers/leaf.rb +28 -0
  46. data/lib/simple_form/wrappers/many.rb +6 -6
  47. data/lib/simple_form/wrappers/root.rb +1 -1
  48. data/lib/simple_form/wrappers/single.rb +5 -3
  49. data/lib/simple_form/wrappers.rb +1 -0
  50. data/lib/simple_form.rb +59 -8
  51. data/test/action_view_extensions/builder_test.rb +36 -36
  52. data/test/action_view_extensions/form_helper_test.rb +33 -14
  53. data/test/components/label_test.rb +37 -37
  54. data/test/form_builder/association_test.rb +52 -35
  55. data/test/form_builder/button_test.rb +10 -10
  56. data/test/form_builder/error_notification_test.rb +1 -1
  57. data/test/form_builder/error_test.rb +147 -22
  58. data/test/form_builder/general_test.rb +89 -64
  59. data/test/form_builder/hint_test.rb +23 -17
  60. data/test/form_builder/input_field_test.rb +80 -16
  61. data/test/form_builder/label_test.rb +52 -10
  62. data/test/form_builder/wrapper_test.rb +135 -19
  63. data/test/generators/simple_form_generator_test.rb +4 -4
  64. data/test/inputs/boolean_input_test.rb +62 -6
  65. data/test/inputs/collection_check_boxes_input_test.rb +85 -17
  66. data/test/inputs/collection_radio_buttons_input_test.rb +134 -36
  67. data/test/inputs/collection_select_input_test.rb +146 -41
  68. data/test/inputs/datetime_input_test.rb +117 -50
  69. data/test/inputs/disabled_test.rb +15 -15
  70. data/test/inputs/discovery_test.rb +56 -6
  71. data/test/inputs/file_input_test.rb +2 -2
  72. data/test/inputs/general_test.rb +20 -20
  73. data/test/inputs/grouped_collection_select_input_test.rb +44 -8
  74. data/test/inputs/hidden_input_test.rb +4 -4
  75. data/test/inputs/numeric_input_test.rb +43 -43
  76. data/test/inputs/priority_input_test.rb +13 -13
  77. data/test/inputs/readonly_test.rb +19 -19
  78. data/test/inputs/required_test.rb +13 -13
  79. data/test/inputs/string_input_test.rb +50 -30
  80. data/test/inputs/text_input_test.rb +7 -7
  81. data/test/simple_form_test.rb +8 -0
  82. data/test/support/discovery_inputs.rb +32 -2
  83. data/test/support/misc_helpers.rb +77 -5
  84. data/test/support/models.rb +60 -24
  85. data/test/test_helper.rb +7 -1
  86. metadata +22 -36
  87. data/lib/simple_form/action_view_extensions/builder.rb.orig +0 -247
  88. data/lib/simple_form/form_builder.rb.orig +0 -486
  89. data/lib/simple_form/version.rb.orig +0 -7
@@ -4,12 +4,12 @@ module SimpleForm
4
4
  desc "Copy SimpleForm default files"
5
5
  source_root File.expand_path('../templates', __FILE__)
6
6
  class_option :template_engine, desc: 'Template engine to be invoked (erb, haml or slim).'
7
- class_option :bootstrap, type: :boolean, desc: 'Add the Twitter Bootstrap wrappers to the SimpleForm initializer.'
8
- class_option :foundation, type: :boolean, desc: 'Add the Zurb Foundation 3 wrappers to the SimpleForm initializer.'
7
+ class_option :bootstrap, type: :boolean, desc: 'Add the Bootstrap wrappers to the SimpleForm initializer.'
8
+ class_option :foundation, type: :boolean, desc: 'Add the Zurb Foundation 5 wrappers to the SimpleForm initializer.'
9
9
 
10
10
  def info_bootstrap
11
11
  return if options.bootstrap? || options.foundation?
12
- puts "SimpleForm 2 supports Twitter Bootstrap and Zurb Foundation 3. If you want "\
12
+ puts "SimpleForm 3 supports Bootstrap and Zurb Foundation 5. If you want "\
13
13
  "a configuration that is compatible with one of these frameworks, then please " \
14
14
  "re-run this generator with --bootstrap or --foundation as an option."
15
15
  end
@@ -1,12 +1,11 @@
1
1
  ===============================================================================
2
2
 
3
3
  Be sure to have a copy of the Bootstrap stylesheet available on your
4
- application, you can get it on http://twitter.github.com/bootstrap.
4
+ application, you can get it on http://getbootstrap.com/.
5
5
 
6
6
  Inside your views, use the 'simple_form_for' with one of the Bootstrap form
7
- classes, '.form-horizontal', '.form-inline', '.form-search' or
8
- '.form-vertical', as the following:
7
+ classes, '.form-horizontal' or '.form-inline', as the following:
9
8
 
10
- = simple_form_for(@user, html: {class: 'form-horizontal' }) do |form|
9
+ = simple_form_for(@user, html: { class: 'form-horizontal' }) do |form|
11
10
 
12
11
  ===============================================================================
@@ -22,9 +22,9 @@ SimpleForm.setup do |config|
22
22
  b.use :placeholder
23
23
 
24
24
  ## Optional extensions
25
- # They are disabled unless you pass `f.input EXTENSION_NAME => :lookup`
25
+ # They are disabled unless you pass `f.input EXTENSION_NAME => true`
26
26
  # to the input. If so, they will retrieve the values from the model
27
- # if any exists. If you want to enable the lookup for any of those
27
+ # if any exists. If you want to enable any of those
28
28
  # extensions by default, you can change `b.optional` to `b.use`.
29
29
 
30
30
  # Calculates maxlength from length validations for string inputs
@@ -43,6 +43,12 @@ SimpleForm.setup do |config|
43
43
  b.use :label_input
44
44
  b.use :hint, wrap_with: { tag: :span, class: :hint }
45
45
  b.use :error, wrap_with: { tag: :span, class: :error }
46
+
47
+ ## full_messages_for
48
+ # If you want to display the full error message for the attribute, you can
49
+ # use the component :full_error, like:
50
+ #
51
+ # b.use :full_error, wrap_with: { tag: :span, class: :error }
46
52
  end
47
53
 
48
54
  # The default wrapper to be used by the FormBuilder.
@@ -66,7 +72,7 @@ SimpleForm.setup do |config|
66
72
  config.error_notification_tag = :div
67
73
 
68
74
  # CSS class to add for error notification helper.
69
- config.error_notification_class = 'alert alert-error'
75
+ config.error_notification_class = 'error_notification'
70
76
 
71
77
  # ID to add for error notification helper.
72
78
  # config.error_notification_id = nil
@@ -92,13 +98,14 @@ SimpleForm.setup do |config|
92
98
  # config.item_wrapper_class = nil
93
99
 
94
100
  # How the label text should be generated altogether with the required text.
95
- # config.label_text = lambda { |label, required| "#{required} #{label}" }
101
+ # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
96
102
 
97
103
  # You can define the class to use on all labels. Default is nil.
98
- config.label_class = 'control-label'
104
+ # config.label_class = nil
99
105
 
100
- # You can define the class to use on all forms. Default is simple_form.
101
- # config.form_class = :simple_form
106
+ # You can define the default class to be used on forms. Can be overriden
107
+ # with `html: { :class }`. Defaulting to none.
108
+ # config.default_form_class = nil
102
109
 
103
110
  # You can define which elements should obtain additional classes
104
111
  # config.generate_additional_classes_for = [:wrapper, :label, :input]
@@ -125,6 +132,10 @@ SimpleForm.setup do |config|
125
132
  # type as key and the wrapper that will be used for all inputs with specified type.
126
133
  # config.wrapper_mappings = { string: :prepend }
127
134
 
135
+ # Namespaces where SimpleForm should look for custom input classes that
136
+ # override default inputs.
137
+ # config.custom_inputs_namespaces << "CustomInputs"
138
+
128
139
  # Default priority for time_zone inputs.
129
140
  # config.time_zone_priority = nil
130
141
 
@@ -142,4 +153,14 @@ SimpleForm.setup do |config|
142
153
 
143
154
  # Default class for inputs
144
155
  # config.input_class = nil
156
+
157
+ # Define the default class of the input wrapper of the boolean input.
158
+ config.boolean_label_class = 'checkbox'
159
+
160
+ # Defines if the default input wrapper class should be included in radio
161
+ # collection wrappers.
162
+ # config.include_default_input_wrapper_class = true
163
+
164
+ # Defines which i18n scope will be used in Simple Form.
165
+ # config.i18n_scope = 'simple_form'
145
166
  end
@@ -1,45 +1,136 @@
1
1
  # Use this setup block to configure all options available in SimpleForm.
2
2
  SimpleForm.setup do |config|
3
- config.wrappers :bootstrap, tag: 'div', class: 'control-group', error_class: 'error' do |b|
3
+ config.error_notification_class = 'alert alert-danger'
4
+ config.button_class = 'btn btn-default'
5
+ config.boolean_label_class = nil
6
+
7
+ config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
4
8
  b.use :html5
5
9
  b.use :placeholder
6
- b.use :label
7
- b.wrapper tag: 'div', class: 'controls' do |ba|
8
- ba.use :input
9
- ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
10
- ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
10
+ b.optional :maxlength
11
+ b.optional :pattern
12
+ b.optional :min_max
13
+ b.optional :readonly
14
+ b.use :label, class: 'control-label'
15
+
16
+ b.use :input, class: 'form-control'
17
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
18
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
19
+ end
20
+
21
+ config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
22
+ b.use :html5
23
+ b.use :placeholder
24
+ b.optional :maxlength
25
+ b.optional :readonly
26
+ b.use :label, class: 'control-label'
27
+
28
+ b.use :input
29
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
30
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
31
+ end
32
+
33
+ config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
34
+ b.use :html5
35
+ b.optional :readonly
36
+
37
+ b.wrapper tag: 'div', class: 'checkbox' do |ba|
38
+ ba.use :label_input
11
39
  end
40
+
41
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
42
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
43
+ end
44
+
45
+ config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
46
+ b.use :html5
47
+ b.optional :readonly
48
+ b.use :label, class: 'control-label'
49
+ b.use :input
50
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
51
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
12
52
  end
13
53
 
14
- config.wrappers :prepend, tag: 'div', class: "control-group", error_class: 'error' do |b|
54
+ config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
15
55
  b.use :html5
16
56
  b.use :placeholder
17
- b.use :label
18
- b.wrapper tag: 'div', class: 'controls' do |input|
19
- input.wrapper tag: 'div', class: 'input-prepend' do |prepend|
20
- prepend.use :input
21
- end
22
- input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
23
- input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
57
+ b.optional :maxlength
58
+ b.optional :pattern
59
+ b.optional :min_max
60
+ b.optional :readonly
61
+ b.use :label, class: 'col-sm-3 control-label'
62
+
63
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
64
+ ba.use :input, class: 'form-control'
65
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
66
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
24
67
  end
25
68
  end
26
69
 
27
- config.wrappers :append, tag: 'div', class: "control-group", error_class: 'error' do |b|
70
+ config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
28
71
  b.use :html5
29
72
  b.use :placeholder
30
- b.use :label
31
- b.wrapper tag: 'div', class: 'controls' do |input|
32
- input.wrapper tag: 'div', class: 'input-append' do |append|
33
- append.use :input
73
+ b.optional :maxlength
74
+ b.optional :readonly
75
+ b.use :label, class: 'col-sm-3 control-label'
76
+
77
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
78
+ ba.use :input
79
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
80
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
81
+ end
82
+ end
83
+
84
+ config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
85
+ b.use :html5
86
+ b.optional :readonly
87
+
88
+ b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
89
+ wr.wrapper tag: 'div', class: 'checkbox' do |ba|
90
+ ba.use :label_input, class: 'col-sm-9'
34
91
  end
35
- input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
36
- input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
92
+
93
+ wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
94
+ wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
37
95
  end
38
96
  end
39
97
 
40
- # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
41
- # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
98
+ config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
99
+ b.use :html5
100
+ b.optional :readonly
101
+
102
+ b.use :label, class: 'col-sm-3 control-label'
103
+
104
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
105
+ ba.use :input
106
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
107
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
108
+ end
109
+ end
110
+
111
+ config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
112
+ b.use :html5
113
+ b.use :placeholder
114
+ b.optional :maxlength
115
+ b.optional :pattern
116
+ b.optional :min_max
117
+ b.optional :readonly
118
+ b.use :label, class: 'sr-only'
119
+
120
+ b.use :input, class: 'form-control'
121
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
122
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
123
+ end
124
+
125
+ # Wrappers for forms and inputs using the Bootstrap toolkit.
126
+ # Check the Bootstrap docs (http://getbootstrap.com)
42
127
  # to learn about the different styles for forms and inputs,
43
128
  # buttons and other elements.
44
- config.default_wrapper = :bootstrap
129
+ config.default_wrapper = :vertical_form
130
+ config.wrapper_mappings = {
131
+ check_boxes: :vertical_radio_and_checkboxes,
132
+ radio_buttons: :vertical_radio_and_checkboxes,
133
+ file: :vertical_file_input,
134
+ boolean: :vertical_boolean,
135
+ }
45
136
  end
@@ -1,6 +1,13 @@
1
1
  # Use this setup block to configure all options available in SimpleForm.
2
2
  SimpleForm.setup do |config|
3
- config.wrappers :foundation, class: :input, hint_class: :field_with_hint, error_class: :error do |b|
3
+ # Don't forget to edit this file to adapt it to your needs (specially
4
+ # all the grid-related classes)
5
+ #
6
+ # Please note that hints are commented out by default since Foundation
7
+ # does't provide styles for hints. You will need to provide your own CSS styles for hints.
8
+ # Uncomment them to enable hints.
9
+
10
+ config.wrappers :vertical_form, class: :input, hint_class: :field_with_hint, error_class: :error do |b|
4
11
  b.use :html5
5
12
  b.use :placeholder
6
13
  b.optional :maxlength
@@ -8,19 +15,93 @@ SimpleForm.setup do |config|
8
15
  b.optional :min_max
9
16
  b.optional :readonly
10
17
  b.use :label_input
11
- b.use :error, wrap_with: { tag: :small }
18
+ b.use :error, wrap_with: { tag: :small, class: :error }
19
+
20
+ # b.use :hint, wrap_with: { tag: :span, class: :hint }
21
+ end
22
+
23
+ config.wrappers :horizontal_form, tag: 'div', class: 'row', hint_class: :field_with_hint, error_class: :error do |b|
24
+ b.use :html5
25
+ b.use :placeholder
26
+ b.optional :maxlength
27
+ b.optional :pattern
28
+ b.optional :min_max
29
+ b.optional :readonly
30
+
31
+ b.wrapper :label_wrapper, tag: :div, class: 'small-3 columns' do |ba|
32
+ ba.use :label, class: 'right inline'
33
+ end
34
+
35
+ b.wrapper :right_input_wrapper, tag: :div, class: 'small-9 columns' do |ba|
36
+ ba.use :input
37
+ ba.use :error, wrap_with: { tag: :small, class: :error }
38
+ # ba.use :hint, wrap_with: { tag: :span, class: :hint }
39
+ end
40
+ end
41
+
42
+ config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'row' do |b|
43
+ b.use :html5
44
+ b.optional :readonly
45
+
46
+ b.wrapper :container_wrapper, tag: 'div', class: 'small-offset-3 small-9 columns' do |ba|
47
+ ba.wrapper :tag => 'label', :class => 'checkbox' do |bb|
48
+ bb.use :input
49
+ bb.use :label_text
50
+ end
12
51
 
13
- # Uncomment the following line to enable hints. The line is commented out by default since Foundation
14
- # does't provide styles for hints. You will need to provide your own CSS styles for hints.
52
+ ba.use :error, wrap_with: { tag: :small, class: :error }
53
+ # ba.use :hint, wrap_with: { tag: :span, class: :hint }
54
+ end
55
+ end
56
+
57
+ # Foundation does not provide a way to handle inline forms
58
+ # This wrapper can be used to create an inline form
59
+ # by hiding that labels on every screen sizes ('hidden-for-small-up').
60
+ #
61
+ # Note that you need to adapt this wrapper to your needs. If you need a 4
62
+ # columns form then change the wrapper class to 'small-3', if you need
63
+ # only two use 'small-6' and so on.
64
+ config.wrappers :inline_form, tag: 'div', class: 'column small-4', hint_class: :field_with_hint, error_class: :error do |b|
65
+ b.use :html5
66
+ b.use :placeholder
67
+ b.optional :maxlength
68
+ b.optional :pattern
69
+ b.optional :min_max
70
+ b.optional :readonly
71
+
72
+ b.use :label, class: 'hidden-for-small-up'
73
+ b.use :input
74
+
75
+ b.use :error, wrap_with: { tag: :small, class: :error }
76
+ # b.use :hint, wrap_with: { tag: :span, class: :hint }
77
+ end
78
+
79
+ # Examples of use:
80
+ # - wrapper_html: {class: 'row'}, custom_wrapper_html: {class: 'column small-12'}
81
+ # - custom_wrapper_html: {class: 'column small-3 end'}
82
+ config.wrappers :customizable_wrapper, tag: 'div', error_class: :error do |b|
83
+ b.use :html5
84
+ b.optional :readonly
85
+
86
+ b.wrapper :custom_wrapper, tag: :div do |ba|
87
+ ba.use :label_input
88
+ end
89
+
90
+ b.use :error, wrap_with: { tag: :small, class: :error }
15
91
  # b.use :hint, wrap_with: { tag: :span, class: :hint }
16
92
  end
17
93
 
18
94
  # CSS class for buttons
19
95
  config.button_class = 'button'
20
96
 
97
+ # Set this to div to make the checkbox and radio properly work
98
+ # otherwise simple_form adds a label tag instead of a div arround
99
+ # the nested label
100
+ config.item_wrapper_tag = :div
101
+
21
102
  # CSS class to add for error notification helper.
22
103
  config.error_notification_class = 'alert-box alert'
23
104
 
24
105
  # The default wrapper to be used by the FormBuilder.
25
- config.default_wrapper = :foundation
106
+ config.default_wrapper = :vertical_form
26
107
  end
@@ -10,7 +10,7 @@ en:
10
10
  # html: '<abbr title="required">*</abbr>'
11
11
  error_notification:
12
12
  default_message: "Please review the problems below:"
13
- # Labels and hints examples
13
+ # Examples
14
14
  # labels:
15
15
  # defaults:
16
16
  # password: 'Password'
@@ -23,4 +23,9 @@ en:
23
23
  # defaults:
24
24
  # username: 'User name to sign in.'
25
25
  # password: 'No special characters, please.'
26
-
26
+ # include_blanks:
27
+ # defaults:
28
+ # age: 'Rather not say'
29
+ # prompts:
30
+ # defaults:
31
+ # age: 'Select your age'
@@ -17,6 +17,7 @@ module SimpleForm
17
17
  options = args.extract_options!
18
18
  options[:wrapper] = self.options[:wrapper] if options[:wrapper].nil?
19
19
  options[:defaults] ||= self.options[:defaults]
20
+ options[:wrapper_mappings] ||= self.options[:wrapper_mappings]
20
21
 
21
22
  if self.class < ActionView::Helpers::FormBuilder
22
23
  options[:builder] ||= self.class
@@ -10,13 +10,17 @@ module SimpleForm
10
10
  #
11
11
  module FormHelper
12
12
 
13
- def simple_form_for(record, options={}, &block)
13
+ def simple_form_for(record, options = {}, &block)
14
14
  options[:builder] ||= SimpleForm::FormBuilder
15
15
  options[:html] ||= {}
16
16
  unless options[:html].key?(:novalidate)
17
17
  options[:html][:novalidate] = !SimpleForm.browser_validations
18
18
  end
19
- 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
20
24
 
21
25
  with_simple_form_field_error_proc do
22
26
  form_for(record, options, &block)
@@ -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,7 +5,7 @@ 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
10
  if has_required?
11
11
  input_html_options[:required] = true
@@ -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
@@ -21,16 +21,19 @@ module SimpleForm
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
@@ -46,6 +49,7 @@ module SimpleForm
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
@@ -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
@@ -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