simple_form-bootstrap 1.1.2 → 1.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.
- checksums.yaml +4 -4
- data/.gitignore +34 -0
- data/.rspec +2 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +36 -0
- data/Rakefile +12 -12
- data/app/assets/javascripts/simple_form-bootstrap.js +24 -24
- data/app/assets/javascripts/simple_form-bootstrap/date_time_input.js +77 -77
- data/app/assets/javascripts/simple_form-bootstrap/select_input.js +12 -12
- data/lib/simple_form/bootstrap.rb +26 -26
- data/lib/simple_form/bootstrap/engine.rb +2 -2
- data/lib/simple_form/bootstrap/form_builders.rb +9 -9
- data/lib/simple_form/bootstrap/form_builders/button.rb +18 -0
- data/lib/simple_form/bootstrap/form_builders/date_time.rb +26 -26
- data/lib/simple_form/bootstrap/inputs.rb +7 -7
- data/lib/simple_form/bootstrap/inputs/date_time_input.rb +135 -135
- data/lib/simple_form/bootstrap/railtie.rb +5 -5
- data/lib/simple_form/bootstrap/setup.rb +189 -189
- data/lib/simple_form/bootstrap/version.rb +1 -1
- data/simple_form-bootstrap.gemspec +40 -0
- data/spec/coverage_helper.rb +63 -0
- data/spec/rails_helper.rb +45 -0
- data/spec/simple_form/bootstrap/form_builders/button_spec.rb +85 -0
- data/spec/simple_form/bootstrap/form_builders/date_time_spec.rb +69 -0
- data/spec/simple_form/simple_form_spec.rb +14 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/support/action_controller.rb +5 -0
- data/spec/support/mock_controller.rb +39 -0
- data/spec/support/rspec_html_matchers.rb +3 -0
- data/spec/support/simple_form.rb +10 -0
- metadata +20 -2
@@ -1,2 +1,2 @@
|
|
1
|
-
class SimpleForm::Bootstrap::Engine < Rails::Engine
|
2
|
-
end
|
1
|
+
class SimpleForm::Bootstrap::Engine < Rails::Engine
|
2
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
module SimpleForm::Bootstrap::FormBuilders
|
2
|
-
extend ActiveSupport::Autoload
|
3
|
-
|
4
|
-
def self.load!
|
5
|
-
Dir.glob("#{__dir__}/form_builders/*") do |path|
|
6
|
-
require path
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
1
|
+
module SimpleForm::Bootstrap::FormBuilders
|
2
|
+
extend ActiveSupport::Autoload
|
3
|
+
|
4
|
+
def self.load!
|
5
|
+
Dir.glob("#{__dir__}/form_builders/*") do |path|
|
6
|
+
require path
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -19,6 +19,24 @@ module SimpleForm::Bootstrap::FormBuilders::Button
|
|
19
19
|
|
20
20
|
super(type, *args, &proc)
|
21
21
|
end
|
22
|
+
|
23
|
+
# Creates a submit button.
|
24
|
+
#
|
25
|
+
# This augments the original button implementation to generate a button element
|
26
|
+
# with a submit action when a block is given. Otherwise, it falls back to the
|
27
|
+
# original submit helper.
|
28
|
+
def submit_button(*args, &block)
|
29
|
+
if block_given?
|
30
|
+
options = args.extract_options!.dup
|
31
|
+
options[:type] = :submit
|
32
|
+
options[:name] ||= 'commit'
|
33
|
+
args << options
|
34
|
+
button_button(options, &block)
|
35
|
+
else
|
36
|
+
submit(*args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
22
40
|
end
|
23
41
|
|
24
42
|
SimpleForm::FormBuilder.class_eval do
|
@@ -1,26 +1,26 @@
|
|
1
|
-
module SimpleForm::Bootstrap::FormBuilders::DateTime
|
2
|
-
DATE_TIME_COLUMN_TYPES = [
|
3
|
-
'datetime',
|
4
|
-
'timestamp',
|
5
|
-
'timestamp without time zone'
|
6
|
-
].freeze
|
7
|
-
|
8
|
-
DATE_COLUMN_TYPES = [
|
9
|
-
'date'
|
10
|
-
].freeze
|
11
|
-
|
12
|
-
def default_input_type(attribute_name, column, options, *args, &block)
|
13
|
-
if (options.is_a?(Hash) ? options[:as] : @options[:as]).nil? && !column.nil?
|
14
|
-
return :bootstrap_date_time if DATE_TIME_COLUMN_TYPES.include?(column.sql_type)
|
15
|
-
return :bootstrap_date if DATE_COLUMN_TYPES.include?(column.sql_type)
|
16
|
-
end
|
17
|
-
|
18
|
-
super(attribute_name, column, options, *args, &block)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
SimpleForm::FormBuilder.class_eval do
|
23
|
-
prepend SimpleForm::Bootstrap::FormBuilders::DateTime
|
24
|
-
|
25
|
-
map_type :bootstrap_date_time, :bootstrap_date, to: SimpleForm::Bootstrap::Inputs::DateTimeInput
|
26
|
-
end
|
1
|
+
module SimpleForm::Bootstrap::FormBuilders::DateTime
|
2
|
+
DATE_TIME_COLUMN_TYPES = [
|
3
|
+
'datetime',
|
4
|
+
'timestamp',
|
5
|
+
'timestamp without time zone'
|
6
|
+
].freeze
|
7
|
+
|
8
|
+
DATE_COLUMN_TYPES = [
|
9
|
+
'date'
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
def default_input_type(attribute_name, column, options, *args, &block)
|
13
|
+
if (options.is_a?(Hash) ? options[:as] : @options[:as]).nil? && !column.nil?
|
14
|
+
return :bootstrap_date_time if DATE_TIME_COLUMN_TYPES.include?(column.sql_type)
|
15
|
+
return :bootstrap_date if DATE_COLUMN_TYPES.include?(column.sql_type)
|
16
|
+
end
|
17
|
+
|
18
|
+
super(attribute_name, column, options, *args, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
SimpleForm::FormBuilder.class_eval do
|
23
|
+
prepend SimpleForm::Bootstrap::FormBuilders::DateTime
|
24
|
+
|
25
|
+
map_type :bootstrap_date_time, :bootstrap_date, to: SimpleForm::Bootstrap::Inputs::DateTimeInput
|
26
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
module SimpleForm::Bootstrap::Inputs
|
2
|
-
extend ActiveSupport::Autoload
|
3
|
-
|
4
|
-
eager_autoload do
|
5
|
-
autoload :DateTimeInput
|
6
|
-
end
|
7
|
-
end
|
1
|
+
module SimpleForm::Bootstrap::Inputs
|
2
|
+
extend ActiveSupport::Autoload
|
3
|
+
|
4
|
+
eager_autoload do
|
5
|
+
autoload :DateTimeInput
|
6
|
+
end
|
7
|
+
end
|
@@ -1,135 +1,135 @@
|
|
1
|
-
# Inspired by this StackOverflow answer: http://stackoverflow.com/a/19018501
|
2
|
-
# I have modified this to work with dates AND times, and also to work better
|
3
|
-
# with browsers with JavaScript disabled.
|
4
|
-
class SimpleForm::Bootstrap::Inputs::DateTimeInput < SimpleForm::Inputs::Base
|
5
|
-
def input(_ = nil)
|
6
|
-
text_field_options = input_html_options.with_indifferent_access
|
7
|
-
format = text_field_options.delete(:format) || default_format
|
8
|
-
|
9
|
-
# Integrate with Bootstrap's styling
|
10
|
-
text_field_options[:class] << 'form-control'
|
11
|
-
|
12
|
-
hidden_field_options = text_field_options.deep_dup
|
13
|
-
hidden_field_options[:class] << 'bootstrap-datepicker'
|
14
|
-
hidden_field_options[:class] << 'bootstrap-timepicker' if input_type == :bootstrap_date_time
|
15
|
-
hidden_field_options[:id] = "#{attribute_name}_hidden"
|
16
|
-
hidden_field_options[:value] ||= format_date(value(object), format)
|
17
|
-
hidden_field_options[:data] = { 'date-format' => strftime_to_momentjs_format(format) }
|
18
|
-
|
19
|
-
hidden_field_group_classes = hidden_field_options[:class].dup
|
20
|
-
hidden_field_group_classes.delete('form-control')
|
21
|
-
|
22
|
-
|
23
|
-
text_field_options[:value] ||= value(object).try(:to_s)
|
24
|
-
|
25
|
-
return_string = <<-END_INPUT
|
26
|
-
<div class="input-group #{hidden_field_group_classes.join(' ')}" style="display: none">
|
27
|
-
#{@builder.hidden_field(attribute_name, hidden_field_options.to_hash)}
|
28
|
-
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
|
29
|
-
</div>
|
30
|
-
#{@builder.text_field(attribute_name, text_field_options.to_hash)}
|
31
|
-
END_INPUT
|
32
|
-
return_string.html_safe
|
33
|
-
end
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
# Gets the format suitable for this field.
|
38
|
-
def default_format
|
39
|
-
case input_type
|
40
|
-
when :bootstrap_date
|
41
|
-
I18n.t('date.formats.default')
|
42
|
-
when :bootstrap_date_time
|
43
|
-
I18n.t('time.formats.default')
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def value(object)
|
48
|
-
object.send @attribute_name if object
|
49
|
-
end
|
50
|
-
|
51
|
-
def format_date(value, format)
|
52
|
-
value.try(:strftime, format)
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
# rubocop:disable Style/CyclomaticComplexity, Style/MethodLength
|
58
|
-
def strftime_to_momentjs_format(format)
|
59
|
-
format.gsub(/([^%]%|^%)([_\-\^][a-zA-Z]|[a-zA-Z])/i) do |match|
|
60
|
-
last_match = Regexp.last_match(2)
|
61
|
-
|
62
|
-
# Preprocess the last match:
|
63
|
-
# - %_m is blank-padding
|
64
|
-
# - %-m is no padding
|
65
|
-
# - %^B is uppercase
|
66
|
-
padding = 0 # zero padding; 1 = blank, 2 = none
|
67
|
-
case last_match[0]
|
68
|
-
when '_'
|
69
|
-
padding = 1
|
70
|
-
last_match = last_match[1]
|
71
|
-
when '-'
|
72
|
-
padding = 2
|
73
|
-
last_match = last_match[1]
|
74
|
-
when '^'
|
75
|
-
last_match = last_match[1]
|
76
|
-
end
|
77
|
-
|
78
|
-
specifier =
|
79
|
-
case last_match
|
80
|
-
when 'a' # Abbreviated day
|
81
|
-
'ddd'
|
82
|
-
when 'A' # Full day
|
83
|
-
'dddd'
|
84
|
-
when 'd' # Day of month, with leading 0
|
85
|
-
padding == 2 ? 'D' : 'DD'
|
86
|
-
when 'u' # Day of year, with leading 0's (3 digits)
|
87
|
-
'DDDD'
|
88
|
-
when 'w' # Day of week, Sunday = 0
|
89
|
-
'd'
|
90
|
-
|
91
|
-
when 'b', 'h' # Abbreviated month
|
92
|
-
'MMM'
|
93
|
-
when 'B' # Full month
|
94
|
-
'MMMM'
|
95
|
-
when 'm' # Two digit representation of month (01 = Jan)
|
96
|
-
padding == 2 ? 'M' : 'MM'
|
97
|
-
|
98
|
-
when 'y' # Two digit representation of the year
|
99
|
-
'YY'
|
100
|
-
when 'Y' # Four digit representation of the year
|
101
|
-
'YYYY'
|
102
|
-
|
103
|
-
when 'H' # Two digit representation of the hour in 24-hour format
|
104
|
-
'HH'
|
105
|
-
when 'k' # Two digit representation of the hour in 24-hour format, padded with space
|
106
|
-
'H'
|
107
|
-
when 'I' # Two digit representation of the hour in 12-hour format
|
108
|
-
'hh'
|
109
|
-
when 'l' # Two digit representation of the hour in 12-hour format, padded with space
|
110
|
-
'h'
|
111
|
-
|
112
|
-
when 'M' # Two digit representation of minute
|
113
|
-
'mm'
|
114
|
-
when 'p' # Uppercase AM or PM
|
115
|
-
'A'
|
116
|
-
when 'P' # Lowercase AM or PM
|
117
|
-
'a'
|
118
|
-
when 'S' # Two digit representation of seconds
|
119
|
-
'ss'
|
120
|
-
|
121
|
-
when 'z' # The time zone offset. e.g. -0500
|
122
|
-
'ZZ'
|
123
|
-
when 'Z' # The time zone offset. e.g. EST
|
124
|
-
'z'
|
125
|
-
else
|
126
|
-
match
|
127
|
-
end
|
128
|
-
|
129
|
-
# Strip the % and return the new specifier
|
130
|
-
match = Regexp.last_match(1)
|
131
|
-
(match.slice(0, match.length - 1) || '') + specifier
|
132
|
-
end
|
133
|
-
end
|
134
|
-
# rubocop:enable Style/CyclomaticComplexity, Style/MethodLength
|
135
|
-
end
|
1
|
+
# Inspired by this StackOverflow answer: http://stackoverflow.com/a/19018501
|
2
|
+
# I have modified this to work with dates AND times, and also to work better
|
3
|
+
# with browsers with JavaScript disabled.
|
4
|
+
class SimpleForm::Bootstrap::Inputs::DateTimeInput < SimpleForm::Inputs::Base
|
5
|
+
def input(_ = nil)
|
6
|
+
text_field_options = input_html_options.with_indifferent_access
|
7
|
+
format = text_field_options.delete(:format) || default_format
|
8
|
+
|
9
|
+
# Integrate with Bootstrap's styling
|
10
|
+
text_field_options[:class] << 'form-control'
|
11
|
+
|
12
|
+
hidden_field_options = text_field_options.deep_dup
|
13
|
+
hidden_field_options[:class] << 'bootstrap-datepicker'
|
14
|
+
hidden_field_options[:class] << 'bootstrap-timepicker' if input_type == :bootstrap_date_time
|
15
|
+
hidden_field_options[:id] = "#{attribute_name}_hidden"
|
16
|
+
hidden_field_options[:value] ||= format_date(value(object), format)
|
17
|
+
hidden_field_options[:data] = { 'date-format' => strftime_to_momentjs_format(format) }
|
18
|
+
|
19
|
+
hidden_field_group_classes = hidden_field_options[:class].dup
|
20
|
+
hidden_field_group_classes.delete('form-control')
|
21
|
+
|
22
|
+
|
23
|
+
text_field_options[:value] ||= value(object).try(:to_s)
|
24
|
+
|
25
|
+
return_string = <<-END_INPUT
|
26
|
+
<div class="input-group #{hidden_field_group_classes.join(' ')}" style="display: none">
|
27
|
+
#{@builder.hidden_field(attribute_name, hidden_field_options.to_hash)}
|
28
|
+
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
|
29
|
+
</div>
|
30
|
+
#{@builder.text_field(attribute_name, text_field_options.to_hash)}
|
31
|
+
END_INPUT
|
32
|
+
return_string.html_safe
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
# Gets the format suitable for this field.
|
38
|
+
def default_format
|
39
|
+
case input_type
|
40
|
+
when :bootstrap_date
|
41
|
+
I18n.t('date.formats.default')
|
42
|
+
when :bootstrap_date_time
|
43
|
+
I18n.t('time.formats.default')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def value(object)
|
48
|
+
object.send @attribute_name if object
|
49
|
+
end
|
50
|
+
|
51
|
+
def format_date(value, format)
|
52
|
+
value.try(:strftime, format)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# rubocop:disable Style/CyclomaticComplexity, Style/MethodLength
|
58
|
+
def strftime_to_momentjs_format(format)
|
59
|
+
format.gsub(/([^%]%|^%)([_\-\^][a-zA-Z]|[a-zA-Z])/i) do |match|
|
60
|
+
last_match = Regexp.last_match(2)
|
61
|
+
|
62
|
+
# Preprocess the last match:
|
63
|
+
# - %_m is blank-padding
|
64
|
+
# - %-m is no padding
|
65
|
+
# - %^B is uppercase
|
66
|
+
padding = 0 # zero padding; 1 = blank, 2 = none
|
67
|
+
case last_match[0]
|
68
|
+
when '_'
|
69
|
+
padding = 1
|
70
|
+
last_match = last_match[1]
|
71
|
+
when '-'
|
72
|
+
padding = 2
|
73
|
+
last_match = last_match[1]
|
74
|
+
when '^'
|
75
|
+
last_match = last_match[1]
|
76
|
+
end
|
77
|
+
|
78
|
+
specifier =
|
79
|
+
case last_match
|
80
|
+
when 'a' # Abbreviated day
|
81
|
+
'ddd'
|
82
|
+
when 'A' # Full day
|
83
|
+
'dddd'
|
84
|
+
when 'd' # Day of month, with leading 0
|
85
|
+
padding == 2 ? 'D' : 'DD'
|
86
|
+
when 'u' # Day of year, with leading 0's (3 digits)
|
87
|
+
'DDDD'
|
88
|
+
when 'w' # Day of week, Sunday = 0
|
89
|
+
'd'
|
90
|
+
|
91
|
+
when 'b', 'h' # Abbreviated month
|
92
|
+
'MMM'
|
93
|
+
when 'B' # Full month
|
94
|
+
'MMMM'
|
95
|
+
when 'm' # Two digit representation of month (01 = Jan)
|
96
|
+
padding == 2 ? 'M' : 'MM'
|
97
|
+
|
98
|
+
when 'y' # Two digit representation of the year
|
99
|
+
'YY'
|
100
|
+
when 'Y' # Four digit representation of the year
|
101
|
+
'YYYY'
|
102
|
+
|
103
|
+
when 'H' # Two digit representation of the hour in 24-hour format
|
104
|
+
'HH'
|
105
|
+
when 'k' # Two digit representation of the hour in 24-hour format, padded with space
|
106
|
+
'H'
|
107
|
+
when 'I' # Two digit representation of the hour in 12-hour format
|
108
|
+
'hh'
|
109
|
+
when 'l' # Two digit representation of the hour in 12-hour format, padded with space
|
110
|
+
'h'
|
111
|
+
|
112
|
+
when 'M' # Two digit representation of minute
|
113
|
+
'mm'
|
114
|
+
when 'p' # Uppercase AM or PM
|
115
|
+
'A'
|
116
|
+
when 'P' # Lowercase AM or PM
|
117
|
+
'a'
|
118
|
+
when 'S' # Two digit representation of seconds
|
119
|
+
'ss'
|
120
|
+
|
121
|
+
when 'z' # The time zone offset. e.g. -0500
|
122
|
+
'ZZ'
|
123
|
+
when 'Z' # The time zone offset. e.g. EST
|
124
|
+
'z'
|
125
|
+
else
|
126
|
+
match
|
127
|
+
end
|
128
|
+
|
129
|
+
# Strip the % and return the new specifier
|
130
|
+
match = Regexp.last_match(1)
|
131
|
+
(match.slice(0, match.length - 1) || '') + specifier
|
132
|
+
end
|
133
|
+
end
|
134
|
+
# rubocop:enable Style/CyclomaticComplexity, Style/MethodLength
|
135
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'rails/railtie'
|
2
|
-
|
3
|
-
class SimpleForm::Bootstrap::Railtie < Rails::Railtie
|
4
|
-
config.eager_load_namespaces << SimpleForm::Bootstrap
|
5
|
-
end
|
1
|
+
require 'rails/railtie'
|
2
|
+
|
3
|
+
class SimpleForm::Bootstrap::Railtie < Rails::Railtie
|
4
|
+
config.eager_load_namespaces << SimpleForm::Bootstrap
|
5
|
+
end
|
@@ -1,189 +1,189 @@
|
|
1
|
-
# Handles configuration Simple Form with Bootstrap defaults.
|
2
|
-
module SimpleForm::Bootstrap::Setup
|
3
|
-
def setup
|
4
|
-
super do |config|
|
5
|
-
yield config
|
6
|
-
configure_simple_form(config)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
def configure_simple_form(config)
|
13
|
-
config.error_notification_tag = :div
|
14
|
-
config.error_notification_class = 'alert alert-danger'
|
15
|
-
config.button_class = 'btn'
|
16
|
-
config.boolean_style = :nested
|
17
|
-
config.boolean_label_class = nil
|
18
|
-
|
19
|
-
configure_wrappers(config)
|
20
|
-
|
21
|
-
# Wrappers for forms and inputs using the Bootstrap toolkit.
|
22
|
-
# Check the Bootstrap docs (http://getbootstrap.com)
|
23
|
-
# to learn about the different styles for forms and inputs,
|
24
|
-
# buttons and other elements.
|
25
|
-
config.default_wrapper = :vertical_form
|
26
|
-
config.wrapper_mappings = {
|
27
|
-
check_boxes: :vertical_radio_and_checkboxes,
|
28
|
-
radio_buttons: :vertical_radio_and_checkboxes,
|
29
|
-
file: :vertical_file_input,
|
30
|
-
boolean: :vertical_boolean,
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
def configure_wrappers(config)
|
35
|
-
configure_vertical_form_wrapper(config)
|
36
|
-
configure_vertical_file_input_wrapper(config)
|
37
|
-
configure_vertical_boolean_wrapper(config)
|
38
|
-
configure_vertical_radio_and_checkboxes_wrapper(config)
|
39
|
-
configure_horizontal_form_wrapper(config)
|
40
|
-
configure_horizontal_file_input_wrapper(config)
|
41
|
-
configure_horizontal_boolean_wrapper(config)
|
42
|
-
configure_horizontal_radio_and_checkboxes_wrapper(config)
|
43
|
-
configure_inline_form_wrapper(config)
|
44
|
-
end
|
45
|
-
|
46
|
-
def configure_vertical_form_wrapper(config)
|
47
|
-
config.wrappers :vertical_form, tag: 'div', class: 'form-group',
|
48
|
-
error_class: 'has-error' do |b|
|
49
|
-
b.use :html5
|
50
|
-
b.use :placeholder
|
51
|
-
b.optional :maxlength
|
52
|
-
b.optional :pattern
|
53
|
-
b.optional :min_max
|
54
|
-
b.optional :readonly
|
55
|
-
b.use :label, class: 'control-label'
|
56
|
-
|
57
|
-
b.use :input, class: 'form-control'
|
58
|
-
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
59
|
-
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def configure_vertical_file_input_wrapper(config)
|
64
|
-
config.wrappers :vertical_file_input, tag: 'div', class: 'form-group',
|
65
|
-
error_class: 'has-error' do |b|
|
66
|
-
b.use :html5
|
67
|
-
b.use :placeholder
|
68
|
-
b.optional :maxlength
|
69
|
-
b.optional :readonly
|
70
|
-
b.use :label, class: 'control-label'
|
71
|
-
|
72
|
-
b.use :input
|
73
|
-
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
74
|
-
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def configure_vertical_boolean_wrapper(config)
|
79
|
-
config.wrappers :vertical_boolean, tag: 'div', class: 'form-group',
|
80
|
-
error_class: 'has-error' do |b|
|
81
|
-
b.use :html5
|
82
|
-
b.optional :readonly
|
83
|
-
|
84
|
-
b.wrapper tag: 'div', class: 'checkbox' do |ba|
|
85
|
-
ba.use :label_input
|
86
|
-
end
|
87
|
-
|
88
|
-
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
89
|
-
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def configure_vertical_radio_and_checkboxes_wrapper(config)
|
94
|
-
config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group',
|
95
|
-
error_class: 'has-error' do |b|
|
96
|
-
b.use :html5
|
97
|
-
b.optional :readonly
|
98
|
-
b.use :label, class: 'control-label'
|
99
|
-
b.use :input
|
100
|
-
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
101
|
-
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def configure_horizontal_form_wrapper(config)
|
106
|
-
config.wrappers :horizontal_form, tag: 'div', class: 'form-group',
|
107
|
-
error_class: 'has-error' do |b|
|
108
|
-
b.use :html5
|
109
|
-
b.use :placeholder
|
110
|
-
b.optional :maxlength
|
111
|
-
b.optional :pattern
|
112
|
-
b.optional :min_max
|
113
|
-
b.optional :readonly
|
114
|
-
b.use :label, class: 'col-sm-3 control-label'
|
115
|
-
|
116
|
-
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
117
|
-
ba.use :input, class: 'form-control'
|
118
|
-
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
119
|
-
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def configure_horizontal_file_input_wrapper(config)
|
125
|
-
config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group',
|
126
|
-
error_class: 'has-error' do |b|
|
127
|
-
b.use :html5
|
128
|
-
b.use :placeholder
|
129
|
-
b.optional :maxlength
|
130
|
-
b.optional :readonly
|
131
|
-
b.use :label, class: 'col-sm-3 control-label'
|
132
|
-
|
133
|
-
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
134
|
-
ba.use :input
|
135
|
-
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
136
|
-
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def configure_horizontal_boolean_wrapper(config)
|
142
|
-
config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group',
|
143
|
-
error_class: 'has-error' do |b|
|
144
|
-
b.use :html5
|
145
|
-
b.optional :readonly
|
146
|
-
|
147
|
-
b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
|
148
|
-
wr.wrapper tag: 'div', class: 'checkbox' do |ba|
|
149
|
-
ba.use :label_input, class: 'col-sm-9'
|
150
|
-
end
|
151
|
-
|
152
|
-
wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
153
|
-
wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def configure_horizontal_radio_and_checkboxes_wrapper(config)
|
159
|
-
config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group',
|
160
|
-
error_class: 'has-error' do |b|
|
161
|
-
b.use :html5
|
162
|
-
b.optional :readonly
|
163
|
-
|
164
|
-
b.use :label, class: 'col-sm-3 control-label'
|
165
|
-
|
166
|
-
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
167
|
-
ba.use :input
|
168
|
-
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
169
|
-
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def configure_inline_form_wrapper(config)
|
175
|
-
config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
176
|
-
b.use :html5
|
177
|
-
b.use :placeholder
|
178
|
-
b.optional :maxlength
|
179
|
-
b.optional :pattern
|
180
|
-
b.optional :min_max
|
181
|
-
b.optional :readonly
|
182
|
-
b.use :label, class: 'sr-only'
|
183
|
-
|
184
|
-
b.use :input, class: 'form-control'
|
185
|
-
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
186
|
-
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
1
|
+
# Handles configuration Simple Form with Bootstrap defaults.
|
2
|
+
module SimpleForm::Bootstrap::Setup
|
3
|
+
def setup
|
4
|
+
super do |config|
|
5
|
+
yield config
|
6
|
+
configure_simple_form(config)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def configure_simple_form(config)
|
13
|
+
config.error_notification_tag = :div
|
14
|
+
config.error_notification_class = 'alert alert-danger'
|
15
|
+
config.button_class = 'btn'
|
16
|
+
config.boolean_style = :nested
|
17
|
+
config.boolean_label_class = nil
|
18
|
+
|
19
|
+
configure_wrappers(config)
|
20
|
+
|
21
|
+
# Wrappers for forms and inputs using the Bootstrap toolkit.
|
22
|
+
# Check the Bootstrap docs (http://getbootstrap.com)
|
23
|
+
# to learn about the different styles for forms and inputs,
|
24
|
+
# buttons and other elements.
|
25
|
+
config.default_wrapper = :vertical_form
|
26
|
+
config.wrapper_mappings = {
|
27
|
+
check_boxes: :vertical_radio_and_checkboxes,
|
28
|
+
radio_buttons: :vertical_radio_and_checkboxes,
|
29
|
+
file: :vertical_file_input,
|
30
|
+
boolean: :vertical_boolean,
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def configure_wrappers(config)
|
35
|
+
configure_vertical_form_wrapper(config)
|
36
|
+
configure_vertical_file_input_wrapper(config)
|
37
|
+
configure_vertical_boolean_wrapper(config)
|
38
|
+
configure_vertical_radio_and_checkboxes_wrapper(config)
|
39
|
+
configure_horizontal_form_wrapper(config)
|
40
|
+
configure_horizontal_file_input_wrapper(config)
|
41
|
+
configure_horizontal_boolean_wrapper(config)
|
42
|
+
configure_horizontal_radio_and_checkboxes_wrapper(config)
|
43
|
+
configure_inline_form_wrapper(config)
|
44
|
+
end
|
45
|
+
|
46
|
+
def configure_vertical_form_wrapper(config)
|
47
|
+
config.wrappers :vertical_form, tag: 'div', class: 'form-group',
|
48
|
+
error_class: 'has-error' do |b|
|
49
|
+
b.use :html5
|
50
|
+
b.use :placeholder
|
51
|
+
b.optional :maxlength
|
52
|
+
b.optional :pattern
|
53
|
+
b.optional :min_max
|
54
|
+
b.optional :readonly
|
55
|
+
b.use :label, class: 'control-label'
|
56
|
+
|
57
|
+
b.use :input, class: 'form-control'
|
58
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
59
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def configure_vertical_file_input_wrapper(config)
|
64
|
+
config.wrappers :vertical_file_input, tag: 'div', class: 'form-group',
|
65
|
+
error_class: 'has-error' do |b|
|
66
|
+
b.use :html5
|
67
|
+
b.use :placeholder
|
68
|
+
b.optional :maxlength
|
69
|
+
b.optional :readonly
|
70
|
+
b.use :label, class: 'control-label'
|
71
|
+
|
72
|
+
b.use :input
|
73
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
74
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def configure_vertical_boolean_wrapper(config)
|
79
|
+
config.wrappers :vertical_boolean, tag: 'div', class: 'form-group',
|
80
|
+
error_class: 'has-error' do |b|
|
81
|
+
b.use :html5
|
82
|
+
b.optional :readonly
|
83
|
+
|
84
|
+
b.wrapper tag: 'div', class: 'checkbox' do |ba|
|
85
|
+
ba.use :label_input
|
86
|
+
end
|
87
|
+
|
88
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
89
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def configure_vertical_radio_and_checkboxes_wrapper(config)
|
94
|
+
config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group',
|
95
|
+
error_class: 'has-error' do |b|
|
96
|
+
b.use :html5
|
97
|
+
b.optional :readonly
|
98
|
+
b.use :label, class: 'control-label'
|
99
|
+
b.use :input
|
100
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
101
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def configure_horizontal_form_wrapper(config)
|
106
|
+
config.wrappers :horizontal_form, tag: 'div', class: 'form-group',
|
107
|
+
error_class: 'has-error' do |b|
|
108
|
+
b.use :html5
|
109
|
+
b.use :placeholder
|
110
|
+
b.optional :maxlength
|
111
|
+
b.optional :pattern
|
112
|
+
b.optional :min_max
|
113
|
+
b.optional :readonly
|
114
|
+
b.use :label, class: 'col-sm-3 control-label'
|
115
|
+
|
116
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
117
|
+
ba.use :input, class: 'form-control'
|
118
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
119
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def configure_horizontal_file_input_wrapper(config)
|
125
|
+
config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group',
|
126
|
+
error_class: 'has-error' do |b|
|
127
|
+
b.use :html5
|
128
|
+
b.use :placeholder
|
129
|
+
b.optional :maxlength
|
130
|
+
b.optional :readonly
|
131
|
+
b.use :label, class: 'col-sm-3 control-label'
|
132
|
+
|
133
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
134
|
+
ba.use :input
|
135
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
136
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def configure_horizontal_boolean_wrapper(config)
|
142
|
+
config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group',
|
143
|
+
error_class: 'has-error' do |b|
|
144
|
+
b.use :html5
|
145
|
+
b.optional :readonly
|
146
|
+
|
147
|
+
b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
|
148
|
+
wr.wrapper tag: 'div', class: 'checkbox' do |ba|
|
149
|
+
ba.use :label_input, class: 'col-sm-9'
|
150
|
+
end
|
151
|
+
|
152
|
+
wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
153
|
+
wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def configure_horizontal_radio_and_checkboxes_wrapper(config)
|
159
|
+
config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group',
|
160
|
+
error_class: 'has-error' do |b|
|
161
|
+
b.use :html5
|
162
|
+
b.optional :readonly
|
163
|
+
|
164
|
+
b.use :label, class: 'col-sm-3 control-label'
|
165
|
+
|
166
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
167
|
+
ba.use :input
|
168
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
169
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def configure_inline_form_wrapper(config)
|
175
|
+
config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
176
|
+
b.use :html5
|
177
|
+
b.use :placeholder
|
178
|
+
b.optional :maxlength
|
179
|
+
b.optional :pattern
|
180
|
+
b.optional :min_max
|
181
|
+
b.optional :readonly
|
182
|
+
b.use :label, class: 'sr-only'
|
183
|
+
|
184
|
+
b.use :input, class: 'form-control'
|
185
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
186
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|