bootstrap_form 4.1.0 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.rubocop.yml +3 -2
- data/.travis.yml +7 -1
- data/CHANGELOG.md +15 -1
- data/CONTRIBUTING.md +11 -0
- data/Dangerfile +4 -4
- data/Gemfile +7 -2
- data/OLD-README.md +795 -0
- data/README.md +150 -93
- data/Rakefile +2 -4
- data/bootstrap_form.gemspec +2 -1
- data/demo/.postcssrc.yml +3 -0
- data/demo/app/assets/config/manifest.js +2 -0
- data/demo/app/assets/stylesheets/actiontext.scss +38 -0
- data/demo/app/assets/stylesheets/application.scss +1 -0
- data/demo/app/helpers/bootstrap_helper.rb +16 -10
- data/demo/app/javascript/channels/consumer.js +6 -0
- data/demo/app/javascript/channels/index.js +5 -0
- data/demo/app/javascript/packs/application.js +11 -0
- data/demo/app/models/user.rb +2 -0
- data/demo/app/views/active_storage/blobs/_blob.html.erb +14 -0
- data/demo/app/views/bootstrap/form.html.erb +2 -1
- data/demo/app/views/layouts/application.html.erb +3 -0
- data/demo/bin/webpack +15 -0
- data/demo/bin/webpack-dev-server +15 -0
- data/demo/config/application.rb +2 -3
- data/demo/config/environments/development.rb +3 -1
- data/demo/config/environments/production.rb +48 -0
- data/demo/config/webpack/development.js +5 -0
- data/demo/config/webpack/environment.js +3 -0
- data/demo/config/webpack/production.js +5 -0
- data/demo/config/webpack/test.js +5 -0
- data/demo/config/webpacker.yml +92 -0
- data/demo/db/schema.rb +63 -18
- data/demo/package.json +13 -1
- data/demo/test/fixtures/action_text/rich_texts.yml +4 -0
- data/demo/yarn.lock +6257 -0
- data/lib/bootstrap_form.rb +34 -8
- data/lib/bootstrap_form/action_view_extensions/form_helper.rb +71 -0
- data/lib/bootstrap_form/components.rb +17 -0
- data/lib/bootstrap_form/components/hints.rb +60 -0
- data/lib/bootstrap_form/components/labels.rb +56 -0
- data/lib/bootstrap_form/components/layout.rb +39 -0
- data/lib/bootstrap_form/components/validation.rb +61 -0
- data/lib/bootstrap_form/engine.rb +10 -0
- data/lib/bootstrap_form/form_builder.rb +54 -524
- data/lib/bootstrap_form/form_group.rb +64 -0
- data/lib/bootstrap_form/form_group_builder.rb +103 -0
- data/lib/bootstrap_form/helpers.rb +9 -0
- data/lib/bootstrap_form/helpers/bootstrap.rb +39 -31
- data/lib/bootstrap_form/inputs.rb +40 -0
- data/lib/bootstrap_form/inputs/base.rb +40 -0
- data/lib/bootstrap_form/inputs/check_box.rb +89 -0
- data/lib/bootstrap_form/inputs/collection_check_boxes.rb +23 -0
- data/lib/bootstrap_form/inputs/collection_radio_buttons.rb +21 -0
- data/lib/bootstrap_form/inputs/collection_select.rb +25 -0
- data/lib/bootstrap_form/inputs/color_field.rb +14 -0
- data/lib/bootstrap_form/inputs/date_field.rb +14 -0
- data/lib/bootstrap_form/inputs/date_select.rb +14 -0
- data/lib/bootstrap_form/inputs/datetime_field.rb +14 -0
- data/lib/bootstrap_form/inputs/datetime_local_field.rb +14 -0
- data/lib/bootstrap_form/inputs/datetime_select.rb +14 -0
- data/lib/bootstrap_form/inputs/email_field.rb +14 -0
- data/lib/bootstrap_form/inputs/file_field.rb +35 -0
- data/lib/bootstrap_form/inputs/grouped_collection_select.rb +29 -0
- data/lib/bootstrap_form/inputs/inputs_collection.rb +44 -0
- data/lib/bootstrap_form/inputs/month_field.rb +14 -0
- data/lib/bootstrap_form/inputs/number_field.rb +14 -0
- data/lib/bootstrap_form/inputs/password_field.rb +14 -0
- data/lib/bootstrap_form/inputs/phone_field.rb +14 -0
- data/lib/bootstrap_form/inputs/radio_button.rb +77 -0
- data/lib/bootstrap_form/inputs/range_field.rb +14 -0
- data/lib/bootstrap_form/inputs/rich_text_area.rb +23 -0
- data/lib/bootstrap_form/inputs/search_field.rb +14 -0
- data/lib/bootstrap_form/inputs/select.rb +22 -0
- data/lib/bootstrap_form/inputs/telephone_field.rb +14 -0
- data/lib/bootstrap_form/inputs/text_area.rb +14 -0
- data/lib/bootstrap_form/inputs/text_field.rb +14 -0
- data/lib/bootstrap_form/inputs/time_field.rb +14 -0
- data/lib/bootstrap_form/inputs/time_select.rb +14 -0
- data/lib/bootstrap_form/inputs/time_zone_select.rb +22 -0
- data/lib/bootstrap_form/inputs/url_field.rb +14 -0
- data/lib/bootstrap_form/inputs/week_field.rb +14 -0
- data/lib/bootstrap_form/version.rb +1 -1
- metadata +79 -6
- data/.rubocop_todo.yml +0 -104
- data/lib/bootstrap_form/aliasing.rb +0 -35
- data/lib/bootstrap_form/helper.rb +0 -52
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Inputs
|
5
|
+
module CollectionCheckBoxes
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Base
|
8
|
+
include InputsCollection
|
9
|
+
|
10
|
+
included do
|
11
|
+
def collection_check_boxes_with_bootstrap(*args)
|
12
|
+
html = inputs_collection(*args) do |name, value, options|
|
13
|
+
options[:multiple] = true
|
14
|
+
check_box(name, options, value, nil)
|
15
|
+
end
|
16
|
+
hidden_field(args.first, value: "", multiple: true).concat(html)
|
17
|
+
end
|
18
|
+
|
19
|
+
bootstrap_alias :collection_check_boxes
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Inputs
|
5
|
+
module CollectionRadioButtons
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Base
|
8
|
+
include InputsCollection
|
9
|
+
|
10
|
+
included do
|
11
|
+
def collection_radio_buttons_with_bootstrap(*args)
|
12
|
+
inputs_collection(*args) do |name, value, options|
|
13
|
+
radio_button(name, value, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
bootstrap_alias :collection_radio_buttons
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Inputs
|
5
|
+
module CollectionSelect
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Base
|
8
|
+
|
9
|
+
included do
|
10
|
+
# Disabling Metrics/ParameterLists because the upstream Rails method has the same parameters
|
11
|
+
# rubocop:disable Metrics/ParameterLists
|
12
|
+
def collection_select_with_bootstrap(method, collection, value_method, text_method, options={}, html_options={})
|
13
|
+
form_group_builder(method, options, html_options) do
|
14
|
+
input_with_error(method) do
|
15
|
+
collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
# rubocop:enable Metrics/ParameterLists
|
20
|
+
|
21
|
+
bootstrap_alias :collection_select
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Inputs
|
5
|
+
module FileField
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Base
|
8
|
+
|
9
|
+
included do
|
10
|
+
def file_field_with_bootstrap(name, options={})
|
11
|
+
options = options.reverse_merge(control_class: "custom-file-input")
|
12
|
+
form_group_builder(name, options) do
|
13
|
+
content_tag(:div, class: "custom-file") do
|
14
|
+
input_with_error(name) do
|
15
|
+
file_field_input(name, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
bootstrap_alias :file_field
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def file_field_input(name, options)
|
27
|
+
placeholder = options.delete(:placeholder) || "Choose file"
|
28
|
+
placeholder_opts = { class: "custom-file-label" }
|
29
|
+
placeholder_opts[:for] = options[:id] if options[:id].present?
|
30
|
+
|
31
|
+
file_field_without_bootstrap(name, options) + label(name, placeholder, placeholder_opts)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Inputs
|
5
|
+
module GroupedCollectionSelect
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Base
|
8
|
+
|
9
|
+
included do
|
10
|
+
# Disabling Metrics/ParameterLists because the upstream Rails method has the same parameters
|
11
|
+
# rubocop:disable Metrics/ParameterLists
|
12
|
+
def grouped_collection_select_with_bootstrap(method, collection, group_method,
|
13
|
+
group_label_method, option_key_method,
|
14
|
+
option_value_method, options={}, html_options={})
|
15
|
+
form_group_builder(method, options, html_options) do
|
16
|
+
input_with_error(method) do
|
17
|
+
grouped_collection_select_without_bootstrap(method, collection, group_method,
|
18
|
+
group_label_method, option_key_method,
|
19
|
+
option_value_method, options, html_options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
# rubocop:enable Metrics/ParameterLists
|
24
|
+
|
25
|
+
bootstrap_alias :grouped_collection_select
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module BootstrapForm
|
2
|
+
module Inputs
|
3
|
+
module InputsCollection
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def inputs_collection(name, collection, value, text, options={})
|
9
|
+
options[:inline] ||= layout_inline?(options[:layout])
|
10
|
+
|
11
|
+
form_group_builder(name, options) do
|
12
|
+
inputs = ActiveSupport::SafeBuffer.new
|
13
|
+
|
14
|
+
collection.each_with_index do |obj, i|
|
15
|
+
input_value = value.respond_to?(:call) ? value.call(obj) : obj.send(value)
|
16
|
+
input_options = form_group_collection_input_options(options, text, obj, i, input_value, collection)
|
17
|
+
inputs << yield(name, input_value, input_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
inputs
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# FIXME: Find a way to reduce the parameter list size
|
25
|
+
# rubocop:disable Metrics/ParameterLists
|
26
|
+
def form_group_collection_input_options(options, text, obj, index, input_value, collection)
|
27
|
+
input_options = options.merge(label: text.respond_to?(:call) ? text.call(obj) : obj.send(text))
|
28
|
+
if (checked = input_options[:checked])
|
29
|
+
input_options[:checked] = form_group_collection_input_checked?(checked, obj, input_value)
|
30
|
+
end
|
31
|
+
|
32
|
+
input_options[:error_message] = index == collection.size - 1
|
33
|
+
input_options.except!(:class)
|
34
|
+
input_options
|
35
|
+
end
|
36
|
+
# rubocop:enable Metrics/ParameterLists
|
37
|
+
|
38
|
+
def form_group_collection_input_checked?(checked, obj, input_value)
|
39
|
+
checked == input_value || Array(checked).try(:include?, input_value) ||
|
40
|
+
checked == obj || Array(checked).try(:include?, obj)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Inputs
|
5
|
+
module RadioButton
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Base
|
8
|
+
|
9
|
+
included do
|
10
|
+
def radio_button_with_bootstrap(name, value, *args)
|
11
|
+
options = args.extract_options!.symbolize_keys!
|
12
|
+
radio_button_options = options.except(:class, :label, :label_class, :error_message, :help,
|
13
|
+
:inline, :custom, :hide_label, :skip_label, :wrapper_class)
|
14
|
+
|
15
|
+
radio_button_options[:class] = radio_button_classes(name, options)
|
16
|
+
|
17
|
+
content_tag(:div, class: radio_button_wrapper_class(options)) do
|
18
|
+
html = radio_button_without_bootstrap(name, value, radio_button_options)
|
19
|
+
html.concat(radio_button_label(name, value, options)) unless options[:skip_label]
|
20
|
+
html.concat(generate_error(name)) if options[:error_message]
|
21
|
+
html
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
bootstrap_alias :radio_button
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def radio_button_label(name, value, options)
|
31
|
+
label_options = { value: value, class: radio_button_label_class(options) }
|
32
|
+
label_options[:for] = options[:id] if options[:id].present?
|
33
|
+
label(name, options[:label], label_options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def radio_button_classes(name, options)
|
37
|
+
classes = [options[:class]]
|
38
|
+
classes << (options[:custom] ? "custom-control-input" : "form-check-input")
|
39
|
+
classes << "is-invalid" if error?(name)
|
40
|
+
classes << "position-static" if options[:skip_label] || options[:hide_label]
|
41
|
+
classes.flatten.compact
|
42
|
+
end
|
43
|
+
|
44
|
+
def radio_button_label_class(options)
|
45
|
+
classes = []
|
46
|
+
classes << (options[:custom] ? "custom-control-label" : "form-check-label")
|
47
|
+
classes << options[:label_class]
|
48
|
+
classes << hide_class if options[:hide_label]
|
49
|
+
classes.flatten.compact
|
50
|
+
end
|
51
|
+
|
52
|
+
def radio_button_wrapper_class(options)
|
53
|
+
classes = []
|
54
|
+
classes << if options[:custom]
|
55
|
+
custom_radio_button_wrapper_class(options)
|
56
|
+
else
|
57
|
+
standard_radio_button_wrapper_class(options)
|
58
|
+
end
|
59
|
+
classes << options[:wrapper_class] if options[:wrapper_class].present?
|
60
|
+
classes.flatten.compact
|
61
|
+
end
|
62
|
+
|
63
|
+
def standard_radio_button_wrapper_class(options)
|
64
|
+
classes = ["form-check"]
|
65
|
+
classes << "form-check-inline" if layout_inline?(options[:inline])
|
66
|
+
classes << "disabled" if options[:disabled]
|
67
|
+
classes
|
68
|
+
end
|
69
|
+
|
70
|
+
def custom_radio_button_wrapper_class(options)
|
71
|
+
classes = ["custom-control", "custom-radio"]
|
72
|
+
classes << "custom-control-inline" if layout_inline?(options[:inline])
|
73
|
+
classes
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|