bootstrap_form 4.1.0 → 4.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 +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
|