simple_form 2.1.3 → 3.0.0.beta1
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.
- data/CHANGELOG.md +6 -54
- data/README.md +129 -111
- data/lib/generators/simple_form/install_generator.rb +4 -4
- data/lib/generators/simple_form/templates/README +2 -2
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +8 -11
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +16 -16
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +3 -3
- data/lib/simple_form.rb +31 -47
- data/lib/simple_form/action_view_extensions/builder.rb +0 -319
- data/lib/simple_form/action_view_extensions/builder.rb.orig +247 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
- data/lib/simple_form/components.rb +1 -1
- data/lib/simple_form/components/errors.rb +1 -7
- data/lib/simple_form/components/hints.rb +2 -7
- data/lib/simple_form/components/html5.rb +1 -1
- data/lib/simple_form/components/labels.rb +4 -4
- data/lib/simple_form/components/maxlength.rb +1 -8
- data/lib/simple_form/error_notification.rb +2 -2
- data/lib/simple_form/form_builder.rb +144 -46
- data/lib/simple_form/form_builder.rb.orig +486 -0
- data/lib/simple_form/helpers.rb +1 -1
- data/lib/simple_form/inputs/base.rb +3 -10
- data/lib/simple_form/inputs/block_input.rb +1 -1
- data/lib/simple_form/inputs/boolean_input.rb +6 -6
- data/lib/simple_form/inputs/collection_input.rb +7 -7
- data/lib/simple_form/inputs/numeric_input.rb +0 -6
- data/lib/simple_form/inputs/password_input.rb +0 -1
- data/lib/simple_form/inputs/string_input.rb +0 -1
- data/lib/simple_form/railtie.rb +7 -0
- data/lib/simple_form/tags.rb +61 -0
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/version.rb.orig +7 -0
- data/lib/simple_form/wrappers.rb +1 -1
- data/lib/simple_form/wrappers/builder.rb +5 -29
- data/lib/simple_form/wrappers/many.rb +1 -1
- data/lib/simple_form/wrappers/root.rb +1 -1
- data/test/action_view_extensions/builder_test.rb +67 -87
- data/test/action_view_extensions/form_helper_test.rb +16 -16
- data/test/components/label_test.rb +46 -46
- data/test/form_builder/association_test.rb +23 -23
- data/test/form_builder/button_test.rb +4 -4
- data/test/form_builder/error_notification_test.rb +8 -8
- data/test/form_builder/error_test.rb +18 -65
- data/test/form_builder/general_test.rb +45 -65
- data/test/form_builder/hint_test.rb +23 -29
- data/test/form_builder/input_field_test.rb +12 -12
- data/test/form_builder/label_test.rb +6 -16
- data/test/form_builder/wrapper_test.rb +21 -21
- data/test/inputs/boolean_input_test.rb +23 -35
- data/test/inputs/collection_check_boxes_input_test.rb +55 -55
- data/test/inputs/collection_radio_buttons_input_test.rb +70 -79
- data/test/inputs/collection_select_input_test.rb +45 -51
- data/test/inputs/datetime_input_test.rb +11 -11
- data/test/inputs/disabled_test.rb +10 -10
- data/test/inputs/discovery_test.rb +4 -4
- data/test/inputs/file_input_test.rb +1 -1
- data/test/inputs/general_test.rb +12 -12
- data/test/inputs/grouped_collection_select_input_test.rb +20 -20
- data/test/inputs/hidden_input_test.rb +1 -1
- data/test/inputs/numeric_input_test.rb +3 -3
- data/test/inputs/priority_input_test.rb +3 -3
- data/test/inputs/readonly_test.rb +12 -12
- data/test/inputs/required_test.rb +5 -5
- data/test/inputs/string_input_test.rb +10 -25
- data/test/inputs/text_input_test.rb +1 -1
- data/test/support/misc_helpers.rb +24 -24
- data/test/support/mock_controller.rb +6 -6
- data/test/support/models.rb +37 -46
- data/test/test_helper.rb +20 -20
- metadata +49 -24
- checksums.yaml +0 -7
- data/lib/simple_form/core_ext/hash.rb +0 -16
@@ -3,13 +3,13 @@ module SimpleForm
|
|
3
3
|
class InstallGenerator < Rails::Generators::Base
|
4
4
|
desc "Copy SimpleForm default files"
|
5
5
|
source_root File.expand_path('../templates', __FILE__)
|
6
|
-
class_option :template_engine, :
|
7
|
-
class_option :bootstrap, :
|
8
|
-
class_option :foundation, :
|
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.'
|
9
9
|
|
10
10
|
def info_bootstrap
|
11
11
|
return if options.bootstrap? || options.foundation?
|
12
|
-
puts "SimpleForm 2 supports Bootstrap and Zurb Foundation 3. If you want "\
|
12
|
+
puts "SimpleForm 2 supports Twitter Bootstrap and Zurb Foundation 3. 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,12 @@
|
|
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://
|
4
|
+
application, you can get it on http://twitter.github.com/bootstrap.
|
5
5
|
|
6
6
|
Inside your views, use the 'simple_form_for' with one of the Bootstrap form
|
7
7
|
classes, '.form-horizontal', '.form-inline', '.form-search' or
|
8
8
|
'.form-vertical', as the following:
|
9
9
|
|
10
|
-
= simple_form_for(@user, :
|
10
|
+
= simple_form_for(@user, html: {class: 'form-horizontal' }) do |form|
|
11
11
|
|
12
12
|
===============================================================================
|
@@ -5,8 +5,8 @@ SimpleForm.setup do |config|
|
|
5
5
|
# wrapper, change the order or even add your own to the
|
6
6
|
# stack. The options given below are used to wrap the
|
7
7
|
# whole input.
|
8
|
-
config.wrappers :default, :
|
9
|
-
:
|
8
|
+
config.wrappers :default, class: :input,
|
9
|
+
hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
10
10
|
## Extensions enabled by default
|
11
11
|
# Any of these extensions can be disabled for a
|
12
12
|
# given input by passing: `f.input EXTENSION_NAME => false`.
|
@@ -18,7 +18,7 @@ SimpleForm.setup do |config|
|
|
18
18
|
b.use :html5
|
19
19
|
|
20
20
|
# Calculates placeholders automatically from I18n
|
21
|
-
# You can also pass a string as f.input :
|
21
|
+
# You can also pass a string as f.input placeholder: "Placeholder"
|
22
22
|
b.use :placeholder
|
23
23
|
|
24
24
|
## Optional extensions
|
@@ -41,8 +41,8 @@ SimpleForm.setup do |config|
|
|
41
41
|
|
42
42
|
## Inputs
|
43
43
|
b.use :label_input
|
44
|
-
b.use :hint, :
|
45
|
-
b.use :error, :
|
44
|
+
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
45
|
+
b.use :error, wrap_with: { tag: :span, class: :error }
|
46
46
|
end
|
47
47
|
|
48
48
|
# The default wrapper to be used by the FormBuilder.
|
@@ -50,8 +50,8 @@ SimpleForm.setup do |config|
|
|
50
50
|
|
51
51
|
# Define the way to render check boxes / radio buttons with labels.
|
52
52
|
# Defaults to :nested for bootstrap config.
|
53
|
-
# :
|
54
|
-
# :
|
53
|
+
# inline: input + label
|
54
|
+
# nested: label > input
|
55
55
|
config.boolean_style = :nested
|
56
56
|
|
57
57
|
# Default class for buttons
|
@@ -120,7 +120,7 @@ SimpleForm.setup do |config|
|
|
120
120
|
|
121
121
|
# Custom wrappers for input types. This should be a hash containing an input
|
122
122
|
# type as key and the wrapper that will be used for all inputs with specified type.
|
123
|
-
# config.wrapper_mappings = { :
|
123
|
+
# config.wrapper_mappings = { string: :prepend }
|
124
124
|
|
125
125
|
# Default priority for time_zone inputs.
|
126
126
|
# config.time_zone_priority = nil
|
@@ -128,9 +128,6 @@ SimpleForm.setup do |config|
|
|
128
128
|
# Default priority for country inputs.
|
129
129
|
# config.country_priority = nil
|
130
130
|
|
131
|
-
# Default size for text inputs.
|
132
|
-
# config.default_input_size = 50
|
133
|
-
|
134
131
|
# When false, do not use translations for labels.
|
135
132
|
# config.translate_labels = true
|
136
133
|
|
@@ -1,44 +1,44 @@
|
|
1
1
|
# Use this setup block to configure all options available in SimpleForm.
|
2
2
|
SimpleForm.setup do |config|
|
3
|
-
config.wrappers :bootstrap, :
|
3
|
+
config.wrappers :bootstrap, tag: 'div', class: 'control-group', error_class: 'error' do |b|
|
4
4
|
b.use :html5
|
5
5
|
b.use :placeholder
|
6
6
|
b.use :label
|
7
|
-
b.wrapper :
|
7
|
+
b.wrapper tag: 'div', class: 'controls' do |ba|
|
8
8
|
ba.use :input
|
9
|
-
ba.use :error, :
|
10
|
-
ba.use :hint, :
|
9
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
|
10
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
config.wrappers :prepend, :
|
14
|
+
config.wrappers :prepend, tag: 'div', class: "control-group", error_class: 'error' do |b|
|
15
15
|
b.use :html5
|
16
16
|
b.use :placeholder
|
17
17
|
b.use :label
|
18
|
-
b.wrapper :
|
19
|
-
input.wrapper :
|
18
|
+
b.wrapper tag: 'div', class: 'controls' do |input|
|
19
|
+
input.wrapper tag: 'div', class: 'input-prepend' do |prepend|
|
20
20
|
prepend.use :input
|
21
21
|
end
|
22
|
-
input.use :hint, :
|
23
|
-
input.use :error, :
|
22
|
+
input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
|
23
|
+
input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
config.wrappers :append, :
|
27
|
+
config.wrappers :append, tag: 'div', class: "control-group", error_class: 'error' do |b|
|
28
28
|
b.use :html5
|
29
29
|
b.use :placeholder
|
30
30
|
b.use :label
|
31
|
-
b.wrapper :
|
32
|
-
input.wrapper :
|
31
|
+
b.wrapper tag: 'div', class: 'controls' do |input|
|
32
|
+
input.wrapper tag: 'div', class: 'input-append' do |append|
|
33
33
|
append.use :input
|
34
34
|
end
|
35
|
-
input.use :hint, :
|
36
|
-
input.use :error, :
|
35
|
+
input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
|
36
|
+
input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
# Wrappers for forms and inputs using the Bootstrap toolkit.
|
41
|
-
# Check the Bootstrap docs (http://
|
40
|
+
# Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
|
41
|
+
# Check the Bootstrap docs (http://twitter.github.com/bootstrap)
|
42
42
|
# to learn about the different styles for forms and inputs,
|
43
43
|
# buttons and other elements.
|
44
44
|
config.default_wrapper = :bootstrap
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Use this setup block to configure all options available in SimpleForm.
|
2
2
|
SimpleForm.setup do |config|
|
3
|
-
config.wrappers :foundation, :
|
3
|
+
config.wrappers :foundation, class: :input, hint_class: :field_with_hint, error_class: :error do |b|
|
4
4
|
b.use :html5
|
5
5
|
b.use :placeholder
|
6
6
|
b.optional :maxlength
|
@@ -8,11 +8,11 @@ SimpleForm.setup do |config|
|
|
8
8
|
b.optional :min_max
|
9
9
|
b.optional :readonly
|
10
10
|
b.use :label_input
|
11
|
-
b.use :error, :
|
11
|
+
b.use :error, wrap_with: { tag: :small }
|
12
12
|
|
13
13
|
# Uncomment the following line to enable hints. The line is commented out by default since Foundation
|
14
14
|
# does't provide styles for hints. You will need to provide your own CSS styles for hints.
|
15
|
-
# b.use :hint, :
|
15
|
+
# b.use :hint, wrap_with: { tag: :span, class: :hint }
|
16
16
|
end
|
17
17
|
|
18
18
|
# CSS class for buttons
|
data/lib/simple_form.rb
CHANGED
@@ -18,6 +18,12 @@ module SimpleForm
|
|
18
18
|
autoload :Inputs
|
19
19
|
end
|
20
20
|
|
21
|
+
def self.eager_load!
|
22
|
+
super
|
23
|
+
SimpleForm::Inputs.eager_load!
|
24
|
+
SimpleForm::Components.eager_load!
|
25
|
+
end
|
26
|
+
|
21
27
|
## CONFIGURATION OPTIONS
|
22
28
|
|
23
29
|
# Method used to tidy up errors.
|
@@ -34,11 +40,11 @@ module SimpleForm
|
|
34
40
|
|
35
41
|
# Series of attemps to detect a default label method for collection.
|
36
42
|
mattr_accessor :collection_label_methods
|
37
|
-
@@collection_label_methods = [
|
43
|
+
@@collection_label_methods = [:to_label, :name, :title, :to_s]
|
38
44
|
|
39
45
|
# Series of attemps to detect a default value method for collection.
|
40
46
|
mattr_accessor :collection_value_methods
|
41
|
-
@@collection_value_methods = [
|
47
|
+
@@collection_value_methods = [:id, :to_s]
|
42
48
|
|
43
49
|
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
44
50
|
mattr_accessor :collection_wrapper_tag
|
@@ -49,7 +55,7 @@ module SimpleForm
|
|
49
55
|
@@collection_wrapper_class = nil
|
50
56
|
|
51
57
|
# You can wrap each item in a collection of radio/check boxes with a tag,
|
52
|
-
# defaulting to
|
58
|
+
# defaulting to span. Please note that when using :boolean_style = :nested,
|
53
59
|
# SimpleForm will force this option to be a :label.
|
54
60
|
mattr_accessor :item_wrapper_tag
|
55
61
|
@@item_wrapper_tag = :span
|
@@ -62,25 +68,25 @@ module SimpleForm
|
|
62
68
|
mattr_accessor :label_text
|
63
69
|
@@label_text = lambda { |label, required| "#{required} #{label}" }
|
64
70
|
|
65
|
-
# You can define the class to
|
71
|
+
# You can define the class to be used on all labels. Defaults to none.
|
66
72
|
mattr_accessor :label_class
|
67
73
|
@@label_class = nil
|
68
74
|
|
69
75
|
# Define the way to render check boxes / radio buttons with labels.
|
70
|
-
# :
|
71
|
-
# :
|
76
|
+
# inline: input + label (default)
|
77
|
+
# nested: label > input
|
72
78
|
mattr_accessor :boolean_style
|
73
79
|
@@boolean_style = :inline
|
74
80
|
|
75
|
-
# You can define the class to
|
81
|
+
# You can define the class to be used on all forms. Default is simple_form.
|
76
82
|
mattr_accessor :form_class
|
77
83
|
@@form_class = :simple_form
|
78
84
|
|
79
|
-
# You can define which elements should obtain additional classes
|
85
|
+
# You can define which elements should obtain additional classes.
|
80
86
|
mattr_accessor :generate_additional_classes_for
|
81
87
|
@@generate_additional_classes_for = [:wrapper, :label, :input]
|
82
88
|
|
83
|
-
# Whether attributes are required by default
|
89
|
+
# Whether attributes are required by default or not.
|
84
90
|
mattr_accessor :required_by_default
|
85
91
|
@@required_by_default = true
|
86
92
|
|
@@ -90,7 +96,7 @@ module SimpleForm
|
|
90
96
|
|
91
97
|
# Collection of methods to detect if a file type was given.
|
92
98
|
mattr_accessor :file_methods
|
93
|
-
@@file_methods = [
|
99
|
+
@@file_methods = [:mounted_as, :file?, :public_filename]
|
94
100
|
|
95
101
|
# Custom mappings for input types. This should be a hash containing a regexp
|
96
102
|
# to match as key, and the input type that will be used when the field name
|
@@ -100,7 +106,7 @@ module SimpleForm
|
|
100
106
|
|
101
107
|
# Custom wrappers for input types. This should be a hash containing an input
|
102
108
|
# type as key and the wrapper that will be used for all inputs with specified type.
|
103
|
-
# e.g { :
|
109
|
+
# e.g { string: :string_wrapper, boolean: :boolean_wrapper }
|
104
110
|
mattr_accessor :wrapper_mappings
|
105
111
|
@@wrapper_mappings = nil
|
106
112
|
|
@@ -112,9 +118,9 @@ module SimpleForm
|
|
112
118
|
mattr_accessor :country_priority
|
113
119
|
@@country_priority = nil
|
114
120
|
|
115
|
-
# Maximum size allowed for inputs.
|
121
|
+
# DEPRECATED: Maximum size allowed for inputs.
|
116
122
|
mattr_accessor :default_input_size
|
117
|
-
@@default_input_size =
|
123
|
+
@@default_input_size = nil
|
118
124
|
|
119
125
|
# When off, do not use translations in labels. Disabling translation in
|
120
126
|
# hints and placeholders can be done manually in the wrapper API.
|
@@ -125,11 +131,11 @@ module SimpleForm
|
|
125
131
|
mattr_accessor :inputs_discovery
|
126
132
|
@@inputs_discovery = true
|
127
133
|
|
128
|
-
# Cache SimpleForm inputs discovery
|
134
|
+
# Cache SimpleForm inputs discovery.
|
129
135
|
mattr_accessor :cache_discovery
|
130
136
|
@@cache_discovery = defined?(Rails) && !Rails.env.development?
|
131
137
|
|
132
|
-
# Adds a class to each generated button, mostly for compatiblity
|
138
|
+
# Adds a class to each generated button, mostly for compatiblity.
|
133
139
|
mattr_accessor :button_class
|
134
140
|
@@button_class = 'button'
|
135
141
|
|
@@ -168,7 +174,7 @@ module SimpleForm
|
|
168
174
|
SimpleForm::Wrappers::Root.new(builder.to_a, options)
|
169
175
|
end
|
170
176
|
|
171
|
-
wrappers :
|
177
|
+
wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
172
178
|
b.use :html5
|
173
179
|
|
174
180
|
b.use :min_max
|
@@ -178,47 +184,25 @@ module SimpleForm
|
|
178
184
|
b.optional :readonly
|
179
185
|
|
180
186
|
b.use :label_input
|
181
|
-
b.use :hint, :
|
182
|
-
b.use :error, :
|
183
|
-
end
|
184
|
-
|
185
|
-
## SETUP
|
186
|
-
|
187
|
-
DEPRECATED = %w(hint_tag hint_class error_tag error_class error_notification_id wrapper_tag wrapper_class wrapper_error_class components html5)
|
188
|
-
@@deprecated = []
|
189
|
-
|
190
|
-
DEPRECATED.each do |method|
|
191
|
-
class_eval "def self.#{method}=(*); @@deprecated << :#{method}=; end"
|
192
|
-
class_eval "def self.#{method}; deprecation_warn 'SimpleForm.#{method} is deprecated and has no effect'; end"
|
193
|
-
end
|
194
|
-
|
195
|
-
def self.translate=(value)
|
196
|
-
deprecation_warn "SimpleForm.translate= is disabled in favor of translate_labels="
|
197
|
-
self.translate_labels = value
|
187
|
+
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
188
|
+
b.use :error, wrap_with: { tag: :span, class: :error }
|
198
189
|
end
|
199
190
|
|
200
|
-
def self.
|
201
|
-
|
202
|
-
self.translate_labels
|
191
|
+
def self.additional_classes_for(component)
|
192
|
+
generate_additional_classes_for.include?(component) ? yield : []
|
203
193
|
end
|
204
194
|
|
205
|
-
|
206
|
-
ActiveSupport::Deprecation.warn "[SIMPLE_FORM] #{message}", caller
|
207
|
-
end
|
195
|
+
## SETUP
|
208
196
|
|
209
|
-
def self.
|
210
|
-
|
197
|
+
def self.default_input_size=(*)
|
198
|
+
ActiveSupport::Deprecation.warn "[SIMPLE_FORM] SimpleForm.default_input_size= is deprecated and has no effect", caller
|
211
199
|
end
|
212
200
|
|
213
201
|
# Default way to setup SimpleForm. Run rails generate simple_form:install
|
214
202
|
# to create a fresh initializer with all configuration values.
|
215
203
|
def self.setup
|
216
204
|
yield self
|
217
|
-
|
218
|
-
unless @@deprecated.empty?
|
219
|
-
raise "[SIMPLE FORM] Your SimpleForm initializer file is using the following methods: #{@@deprecated.to_sentence}. " <<
|
220
|
-
"Those methods are part of the outdated configuration API. Updating to the new API is easy and fast. " <<
|
221
|
-
"Check for more info here: https://github.com/plataformatec/simple_form/wiki/Upgrading-to-Simple-Form-2.0"
|
222
|
-
end
|
223
205
|
end
|
224
206
|
end
|
207
|
+
|
208
|
+
require 'simple_form/railtie' if defined?(Rails)
|
@@ -1,188 +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_name = html_options[:name] || "#{object_name}[#{attribute}][]"
|
182
|
-
hidden = @template.hidden_field_tag(hidden_name, "", :id => nil)
|
183
|
-
|
184
|
-
wrap_rendered_collection(rendered_collection + hidden, options)
|
185
|
-
end
|
186
6
|
|
187
7
|
# Wrapper for using SimpleForm inside a default rails form.
|
188
8
|
# Example:
|
@@ -205,72 +25,6 @@ module SimpleForm
|
|
205
25
|
end
|
206
26
|
fields_for(*(args << options), &block)
|
207
27
|
end
|
208
|
-
|
209
|
-
private
|
210
|
-
|
211
|
-
def instantiate_collection_builder(builder_class, attribute, item, value, text, html_options)
|
212
|
-
builder_class.new(self, attribute, item,
|
213
|
-
sanitize_attribute_name(attribute, value), text, value, html_options)
|
214
|
-
end
|
215
|
-
|
216
|
-
# Generate default options for collection helpers, such as :checked and
|
217
|
-
# :disabled.
|
218
|
-
def default_html_options_for_collection(item, value, options, html_options) #:nodoc:
|
219
|
-
html_options = html_options.dup
|
220
|
-
|
221
|
-
[:checked, :selected, :disabled].each do |option|
|
222
|
-
current_option = options[option]
|
223
|
-
next if current_option.nil?
|
224
|
-
|
225
|
-
accept = if current_option.respond_to?(:call)
|
226
|
-
current_option.call(item)
|
227
|
-
else
|
228
|
-
Array(current_option).map(&:to_s).include?(value.to_s)
|
229
|
-
end
|
230
|
-
|
231
|
-
if accept
|
232
|
-
html_options[option] = true
|
233
|
-
elsif option == :checked
|
234
|
-
html_options[option] = false
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
html_options
|
239
|
-
end
|
240
|
-
|
241
|
-
def sanitize_attribute_name(attribute, value) #:nodoc:
|
242
|
-
"#{attribute}_#{value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase}"
|
243
|
-
end
|
244
|
-
|
245
|
-
def render_collection(collection, value_method, text_method, options={}, html_options={}) #:nodoc:
|
246
|
-
item_wrapper_tag = options.fetch(:item_wrapper_tag, :span)
|
247
|
-
item_wrapper_class = options[:item_wrapper_class]
|
248
|
-
|
249
|
-
collection.map do |item|
|
250
|
-
value = value_for_collection(item, value_method)
|
251
|
-
text = value_for_collection(item, text_method)
|
252
|
-
default_html_options = default_html_options_for_collection(item, value, options, html_options)
|
253
|
-
|
254
|
-
rendered_item = yield item, value, text, default_html_options
|
255
|
-
|
256
|
-
item_wrapper_tag ? @template.content_tag(item_wrapper_tag, rendered_item, :class => item_wrapper_class) : rendered_item
|
257
|
-
end.join.html_safe
|
258
|
-
end
|
259
|
-
|
260
|
-
def value_for_collection(item, value) #:nodoc:
|
261
|
-
value.respond_to?(:call) ? value.call(item) : item.send(value)
|
262
|
-
end
|
263
|
-
|
264
|
-
def wrap_rendered_collection(collection, options)
|
265
|
-
wrapper_tag = options[:collection_wrapper_tag]
|
266
|
-
|
267
|
-
if wrapper_tag
|
268
|
-
wrapper_class = options[:collection_wrapper_class]
|
269
|
-
@template.content_tag(wrapper_tag, collection, :class => wrapper_class)
|
270
|
-
else
|
271
|
-
collection
|
272
|
-
end
|
273
|
-
end
|
274
28
|
end
|
275
29
|
end
|
276
30
|
end
|
@@ -279,77 +33,4 @@ module ActionView::Helpers
|
|
279
33
|
class FormBuilder
|
280
34
|
include SimpleForm::ActionViewExtensions::Builder
|
281
35
|
end
|
282
|
-
|
283
|
-
module FormOptionsHelper
|
284
|
-
# Override Rails options_from_collection_for_select to handle lambdas/procs in
|
285
|
-
# text and value methods, so it works the same way as collection_radio_buttons
|
286
|
-
# and collection_check_boxes in SimpleForm. If none of text/value methods is a
|
287
|
-
# callable object, then it just delegates back to original collection select.
|
288
|
-
# FIXME: remove when support only Rails 4.0 forward
|
289
|
-
# https://github.com/rails/rails/commit/9035324367526af0300477a58b6d3efc15d1a5a8
|
290
|
-
alias :original_options_from_collection_for_select :options_from_collection_for_select
|
291
|
-
def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
|
292
|
-
if value_method.respond_to?(:call) || text_method.respond_to?(:call)
|
293
|
-
collection = collection.map do |item|
|
294
|
-
value = value_for_collection(item, value_method)
|
295
|
-
text = value_for_collection(item, text_method)
|
296
|
-
|
297
|
-
[value, text]
|
298
|
-
end
|
299
|
-
|
300
|
-
value_method, text_method = :first, :last
|
301
|
-
selected = extract_selected_and_disabled_and_call_procs selected, collection
|
302
|
-
end
|
303
|
-
|
304
|
-
original_options_from_collection_for_select collection, value_method, text_method, selected
|
305
|
-
end
|
306
|
-
|
307
|
-
private
|
308
|
-
|
309
|
-
def extract_selected_and_disabled_and_call_procs(selected, collection)
|
310
|
-
selected, disabled = extract_selected_and_disabled selected
|
311
|
-
selected_disabled = { :selected => selected, :disabled => disabled }
|
312
|
-
|
313
|
-
selected_disabled.each do |key, check|
|
314
|
-
if check.is_a? Proc
|
315
|
-
values = collection.map { |option| option.first if check.call(option.first) }
|
316
|
-
selected_disabled[key] = values
|
317
|
-
end
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
def value_for_collection(item, value) #:nodoc:
|
322
|
-
value.respond_to?(:call) ? value.call(item) : item.send(value)
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
# Backport Rails fix to checkbox tag element, which does not generate the
|
327
|
-
# hidden input when given nil as unchecked value. This is to make SimpleForm
|
328
|
-
# collection check boxes helper to work fine with nested boolean style, when
|
329
|
-
# they are wrapped in labels. Without that, clicking in the label would
|
330
|
-
# actually change the hidden input, instead of the checkbox.
|
331
|
-
# FIXME: remove when support only Rails >= 3.2.2.
|
332
|
-
class InstanceTag
|
333
|
-
def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
|
334
|
-
options = options.stringify_keys
|
335
|
-
options["type"] = "checkbox"
|
336
|
-
options["value"] = checked_value
|
337
|
-
if options.has_key?("checked")
|
338
|
-
cv = options.delete "checked"
|
339
|
-
checked = cv == true || cv == "checked"
|
340
|
-
else
|
341
|
-
checked = self.class.check_box_checked?(value(object), checked_value)
|
342
|
-
end
|
343
|
-
options["checked"] = "checked" if checked
|
344
|
-
if options["multiple"]
|
345
|
-
add_default_name_and_id_for_value(checked_value, options)
|
346
|
-
options.delete("multiple")
|
347
|
-
else
|
348
|
-
add_default_name_and_id(options)
|
349
|
-
end
|
350
|
-
hidden = unchecked_value ? tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value, "disabled" => options["disabled"]) : "".html_safe
|
351
|
-
checkbox = tag("input", options)
|
352
|
-
hidden + checkbox
|
353
|
-
end
|
354
|
-
end
|
355
36
|
end
|