bootstrap_form 4.5.0 → 5.0.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +46 -0
  3. data/.gitignore +16 -1
  4. data/.rubocop.yml +17 -14
  5. data/CHANGELOG.md +32 -1
  6. data/CONTRIBUTING.md +65 -5
  7. data/Dangerfile +5 -7
  8. data/Dockerfile +26 -0
  9. data/Gemfile +4 -3
  10. data/README.md +63 -40
  11. data/UPGRADE-4.0.md +1 -1
  12. data/UPGRADE-5.0.md +25 -0
  13. data/bootstrap_form.gemspec +8 -6
  14. data/demo/app/assets/config/manifest.js +1 -2
  15. data/demo/app/helpers/bootstrap_helper.rb +4 -4
  16. data/demo/app/views/bootstrap/form.html.erb +13 -0
  17. data/demo/app/views/layouts/application.html.erb +3 -3
  18. data/demo/config/environments/development.rb +1 -1
  19. data/demo/config/puma.rb +2 -2
  20. data/demo/db/schema.rb +2 -2
  21. data/docker-compose.yml +70 -0
  22. data/gemfiles/5.2.gemfile +2 -15
  23. data/gemfiles/6.0.gemfile +2 -17
  24. data/gemfiles/6.1.gemfile +4 -0
  25. data/gemfiles/edge.gemfile +2 -17
  26. data/lib/bootstrap_form/components/labels.rb +1 -1
  27. data/lib/bootstrap_form/components/validation.rb +1 -1
  28. data/lib/bootstrap_form/configuration.rb +1 -2
  29. data/lib/bootstrap_form/form_builder.rb +2 -4
  30. data/lib/bootstrap_form/form_group.rb +21 -10
  31. data/lib/bootstrap_form/form_group_builder.rb +6 -8
  32. data/lib/bootstrap_form/helpers/bootstrap.rb +11 -10
  33. data/lib/bootstrap_form/inputs/base.rb +5 -5
  34. data/lib/bootstrap_form/inputs/check_box.rb +8 -22
  35. data/lib/bootstrap_form/inputs/collection_select.rb +1 -0
  36. data/lib/bootstrap_form/inputs/file_field.rb +3 -15
  37. data/lib/bootstrap_form/inputs/grouped_collection_select.rb +1 -0
  38. data/lib/bootstrap_form/inputs/radio_button.rb +7 -25
  39. data/lib/bootstrap_form/inputs/select.rb +1 -0
  40. data/lib/bootstrap_form/inputs/time_zone_select.rb +1 -0
  41. data/lib/bootstrap_form/version.rb +1 -1
  42. data/lib/bootstrap_form.rb +1 -2
  43. metadata +24 -6
  44. data/.travis.yml +0 -35
@@ -3,6 +3,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  require "bootstrap_form/version"
5
5
 
6
+ REQUIRED_RAILS_VERSION = ">= 5.2".freeze
7
+
6
8
  Gem::Specification.new do |s|
7
9
  s.name = "bootstrap_form"
8
10
  s.version = BootstrapForm::VERSION
@@ -10,13 +12,11 @@ Gem::Specification.new do |s|
10
12
  s.email = ["potenza@gmail.com", "carlos.el.lopes@gmail.com"]
11
13
  s.homepage = "https://github.com/bootstrap-ruby/bootstrap_form"
12
14
  s.summary = "Rails form builder that makes it easy to style forms using "\
13
- "Bootstrap 4"
15
+ "Bootstrap 5"
14
16
  s.description = "bootstrap_form is a rails form builder that makes it super "\
15
- "easy to create beautiful-looking forms using Bootstrap 4"
17
+ "easy to create beautiful-looking forms using Bootstrap 5"
16
18
  s.license = "MIT"
17
19
 
18
- s.post_install_message = "Default form attribute role=\"form\" will be dropped in 5.0.0"
19
-
20
20
  s.files = `git ls-files -z`.split("\x0").reject do |f|
21
21
  f.match(%r{^(test)/})
22
22
  end
@@ -26,6 +26,8 @@ Gem::Specification.new do |s|
26
26
 
27
27
  s.required_ruby_version = ">= 2.5"
28
28
 
29
- s.add_dependency("actionpack", ">= 5.2")
30
- s.add_dependency("activemodel", ">= 5.2")
29
+ s.add_dependency("actionpack", REQUIRED_RAILS_VERSION)
30
+ s.add_dependency("activemodel", REQUIRED_RAILS_VERSION)
31
+
32
+ s.add_development_dependency("rails", REQUIRED_RAILS_VERSION)
31
33
  end
@@ -1,2 +1 @@
1
- //= link_tree ../images
2
- //= link_directory ../stylesheets .css
1
+ //= link application.css
@@ -2,7 +2,7 @@ module BootstrapHelper
2
2
  def form_with_source(&block)
3
3
  form_html = capture(&block)
4
4
 
5
- content_tag(:div, class: "example") do
5
+ tag.div(class: "example") do
6
6
  concat(form_html)
7
7
  concat(toggle)
8
8
  concat(codemirror(form_html))
@@ -12,15 +12,15 @@ module BootstrapHelper
12
12
  private
13
13
 
14
14
  def codemirror(form_html)
15
- content_tag(:div, class: "code", style: "display: none") do
16
- content_tag(:textarea, class: "codemirror") do
15
+ tag.div(class: "code", style: "display: none") do
16
+ tag.textarea(class: "codemirror") do
17
17
  HtmlBeautifier.beautify(form_html.strip.gsub(">", ">\n").gsub("<", "\n<"))
18
18
  end
19
19
  end
20
20
  end
21
21
 
22
22
  def toggle
23
- content_tag(:button, class: "toggle btn btn-sm btn-info") do
23
+ tag.button(class: "toggle btn btn-sm btn-info") do
24
24
  "Show Source Code"
25
25
  end
26
26
  end
@@ -52,3 +52,16 @@
52
52
  <%= form.submit %>
53
53
  <% end %>
54
54
  <% end %>
55
+
56
+ <h3>Floating Labels</h3>
57
+
58
+ <%= form_with_source do %>
59
+ <%= bootstrap_form_for @user do |form| %>
60
+ <%= form.email_field :email, placeholder: "Enter Email", label: "Email address", help: "We'll never share your email with anyone else", floating: true %>
61
+ <%= form.password_field :password, placeholder: "Password", floating: true %>
62
+ <%= form.text_field :misc, floating: true %>
63
+ <%= form.text_area :comments, floating: true %>
64
+ <%= form.select :status, [["Active", 1], ["Inactive", 2]], include_blank: "Select a value", floating: true %>
65
+ <%= form.submit %>
66
+ <% end %>
67
+ <% end %>
@@ -6,7 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7
7
 
8
8
  <!-- Bootstrap CSS -->
9
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
9
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
10
10
 
11
11
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.33.0/codemirror.min.css">
12
12
 
@@ -44,8 +44,8 @@
44
44
  <!-- Optional JavaScript -->
45
45
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
46
46
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
47
- <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
48
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
47
+ <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js" integrity="sha384-SR1sx49pcuLnqZUnnPwx6FCym0wLsk5JZuNx2bPPENzswTNFaQU1RDvt3wT4gWFG" crossorigin="anonymous"></script>
48
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.min.js" integrity="sha384-j0CNLUeiqtyaRmlzUHCPZ+Gy5fQu0dQ6eZ/xAww941Ai1SxSY+0EQqNXNE6DZiVc" crossorigin="anonymous"></script>
49
49
 
50
50
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.33.0/codemirror.min.js"></script>
51
51
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.33.0/mode/htmlmixed/htmlmixed.min.js"></script>
@@ -16,7 +16,7 @@ Rails.application.configure do
16
16
 
17
17
  # Enable/disable caching. By default caching is disabled.
18
18
  # Run rails dev:cache to toggle caching.
19
- if Rails.root.join("tmp", "caching-dev.txt").exist?
19
+ if Rails.root.join("tmp/caching-dev.txt").exist?
20
20
  config.action_controller.perform_caching = true
21
21
 
22
22
  config.cache_store = :memory_store
data/demo/config/puma.rb CHANGED
@@ -4,12 +4,12 @@
4
4
  # the maximum value specified for Puma. Default is set to 5 threads for minimum
5
5
  # and maximum; this matches the default thread size of Active Record.
6
6
  #
7
- threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
7
+ threads_count = ENV.fetch("RAILS_MAX_THREADS", 5)
8
8
  threads threads_count, threads_count
9
9
 
10
10
  # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
11
11
  #
12
- port ENV.fetch("PORT") { 3000 }
12
+ port ENV.fetch("PORT", 3000)
13
13
 
14
14
  # Specifies the `environment` that Puma will run in.
15
15
  #
data/demo/db/schema.rb CHANGED
@@ -2,8 +2,8 @@
2
2
  # of editing this file, please use the migrations feature of Active Record to
3
3
  # incrementally modify your database, and then regenerate this schema definition.
4
4
  #
5
- # This file is the source Rails uses to define your schema when running `rails
6
- # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
7
  # be faster and is potentially less error prone than running all of your
8
8
  # migrations from scratch. Old migrations may fail to apply correctly if those
9
9
  # migrations use external dependencies or application code.
@@ -0,0 +1,70 @@
1
+ version: '2.4'
2
+
3
+ services:
4
+ app: &app
5
+ build:
6
+ context: .
7
+ args:
8
+ RUBY_VERSION: '2.7.1'
9
+ NODE_MAJOR: '12'
10
+ YARN_VERSION: '1.22.4'
11
+ BUNDLER_VERSION: '2.1.4'
12
+ image: bootstrap-form:0.0.1
13
+ tmpfs:
14
+ - /tmp
15
+
16
+ backend: &backend
17
+ <<: *app
18
+ stdin_open: true
19
+ tty: true
20
+ volumes:
21
+ - .:/app:cached
22
+ - rails_cache:/app/tmp/cache
23
+ - bundle:/usr/local/bundle
24
+ - node_modules:/app/node_modules
25
+ - packs:/app/public/packs
26
+ environment:
27
+ - NODE_ENV=development
28
+ - RAILS_ENV=${RAILS_ENV:-development}
29
+ - BOOTSNAP_CACHE_DIR=/usr/local/bundle/_bootsnap
30
+ - WEBPACKER_DEV_SERVER_HOST=webpacker
31
+ - WEB_CONCURRENCY=1
32
+ - HISTFILE=/app/.bash_history
33
+ - EDITOR=vi
34
+
35
+ shell:
36
+ <<: *backend
37
+ command: /bin/bash
38
+ ports:
39
+ - '3000:3000'
40
+
41
+ server:
42
+ <<: *backend
43
+ command: sh -c "cd demo/app && bundle exec rails server -b 0.0.0.0"
44
+ ports:
45
+ - '3000:3000'
46
+
47
+ test:
48
+ <<: *backend
49
+ command: rake test
50
+
51
+ webpacker:
52
+ <<: *app
53
+ command: ./bin/webpack-dev-server
54
+ ports:
55
+ - '3035:3035'
56
+ volumes:
57
+ - .:/app:cached
58
+ - bundle:/usr/local/bundle
59
+ - node_modules:/app/node_modules
60
+ - packs:/app/public/packs
61
+ environment:
62
+ - NODE_ENV=${NODE_ENV:-development}
63
+ - RAILS_ENV=${RAILS_ENV:-development}
64
+ - WEBPACKER_DEV_SERVER_HOST=0.0.0.0
65
+
66
+ volumes:
67
+ bundle:
68
+ node_modules:
69
+ rails_cache:
70
+ packs:
data/gemfiles/5.2.gemfile CHANGED
@@ -1,17 +1,4 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: "../"
1
+ gems = "#{File.dirname __dir__}/Gemfile"
2
+ eval File.read(gems), binding, gems # rubocop: disable Security/Eval
4
3
 
5
4
  gem "rails", "~> 5.2.0"
6
-
7
- group :development do
8
- gem "rubocop-rails", require: false
9
- end
10
-
11
- group :test do
12
- gem "diffy"
13
- gem "equivalent-xml"
14
- gem "mocha"
15
- gem "sqlite3", "~> 1.4"
16
- gem "timecop", "~> 0.7.1"
17
- end
data/gemfiles/6.0.gemfile CHANGED
@@ -1,19 +1,4 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: "../"
1
+ gems = "#{File.dirname __dir__}/Gemfile"
2
+ eval File.read(gems), binding, gems # rubocop: disable Security/Eval
4
3
 
5
4
  gem "rails", "~> 6.0.0"
6
-
7
- group :development do
8
- gem "rubocop-rails", require: false
9
- gem "sassc"
10
- gem "webpacker", ">= 4.0.0.rc.3"
11
- end
12
-
13
- group :test do
14
- gem "diffy"
15
- gem "equivalent-xml"
16
- gem "mocha"
17
- gem "sqlite3"
18
- gem "timecop", "~> 0.7.1"
19
- end
@@ -0,0 +1,4 @@
1
+ gems = "#{File.dirname __dir__}/Gemfile"
2
+ eval File.read(gems), binding, gems # rubocop: disable Security/Eval
3
+
4
+ gem "rails", "~> 6.1.0"
@@ -1,19 +1,4 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: "../"
1
+ gems = "#{File.dirname __dir__}/Gemfile"
2
+ eval File.read(gems), binding, gems # rubocop: disable Security/Eval
4
3
 
5
4
  gem "rails", git: "https://github.com/rails/rails.git"
6
-
7
- group :development do
8
- gem "rubocop-rails", require: false
9
- gem "sassc-rails"
10
- gem "webpacker"
11
- end
12
-
13
- group :test do
14
- gem "diffy"
15
- gem "equivalent-xml"
16
- gem "mocha"
17
- gem "sqlite3"
18
- gem "timecop", "~> 0.7.1"
19
- end
@@ -23,7 +23,7 @@ module BootstrapForm
23
23
  end
24
24
 
25
25
  def label_classes(name, options, custom_label_col, group_layout)
26
- classes = [options[:class], label_layout_classes(custom_label_col, group_layout)]
26
+ classes = ["form-label", options[:class], label_layout_classes(custom_label_col, group_layout)]
27
27
 
28
28
  case options.delete(:required)
29
29
  when true
@@ -14,7 +14,7 @@ module BootstrapForm
14
14
  def required_attribute?(obj, attribute)
15
15
  return false unless obj && attribute
16
16
 
17
- target = obj.class == Class ? obj : obj.class
17
+ target = obj.instance_of?(Class) ? obj : obj.class
18
18
 
19
19
  target_validators = if target.respond_to? :validators_on
20
20
  target.validators_on(attribute).map(&:class)
@@ -16,8 +16,7 @@ module BootstrapForm
16
16
  def default_form_attributes
17
17
  return @default_form_attributes if defined? @default_form_attributes
18
18
 
19
- # TODO: Return blank hash ({}) in 5.0.0. Role "form" for form tags is redundant and makes W3C to raise a warning.
20
- { role: "form" }
19
+ {}
21
20
  end
22
21
  end
23
22
  end
@@ -43,9 +43,8 @@ module BootstrapForm
43
43
  include BootstrapForm::Inputs::UrlField
44
44
  include BootstrapForm::Inputs::WeekField
45
45
 
46
- delegate :content_tag, :capture, :concat, to: :@template
46
+ delegate :content_tag, :capture, :concat, :tag, to: :@template
47
47
 
48
- # rubocop:disable Metrics/AbcSize
49
48
  def initialize(object_name, object, template, options)
50
49
  @layout = options[:layout] || default_layout
51
50
  @label_col = options[:label_col] || default_label_col
@@ -61,7 +60,6 @@ module BootstrapForm
61
60
  add_default_form_attributes_and_form_inline options
62
61
  super
63
62
  end
64
- # rubocop:enable Metrics/AbcSize
65
63
 
66
64
  def add_default_form_attributes_and_form_inline(options)
67
65
  options[:html] ||= {}
@@ -69,7 +67,7 @@ module BootstrapForm
69
67
 
70
68
  return unless options[:layout] == :inline
71
69
 
72
- options[:html][:class] = [options[:html][:class], "form-inline"].compact.join(" ")
70
+ options[:html][:class] = [options[:html][:class], "col-auto", "g-3"].compact.join(" ")
73
71
  end
74
72
 
75
73
  def fields_for_with_bootstrap(record_name, record_object=nil, fields_options={}, &block)
@@ -10,9 +10,9 @@ module BootstrapForm
10
10
 
11
11
  options[:class] = form_group_classes(options)
12
12
 
13
- content_tag(:div, options.except(:append, :id, :label, :help, :icon,
14
- :input_group_class, :label_col, :control_col,
15
- :add_control_col_class, :layout, :prepend)) do
13
+ tag.div(**options.except(:append, :id, :label, :help, :icon,
14
+ :input_group_class, :label_col, :control_col,
15
+ :add_control_col_class, :layout, :prepend, :floating)) do
16
16
  form_group_content(
17
17
  generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]),
18
18
  generate_help(name, options[:help]), options, &block
@@ -24,8 +24,8 @@ module BootstrapForm
24
24
 
25
25
  def form_group_content_tag(name, field_name, without_field_name, options, html_options)
26
26
  html_class = control_specific_class(field_name)
27
- html_class = "#{html_class} form-inline" if @layout == :horizontal && options[:skip_inline].blank?
28
- content_tag(:div, class: html_class) do
27
+ html_class = "#{html_class} col-auto g-3" if @layout == :horizontal && options[:skip_inline].blank?
28
+ tag.div(class: html_class) do
29
29
  input_with_error(name) do
30
30
  send(without_field_name, name, options, html_options)
31
31
  end
@@ -34,10 +34,12 @@ module BootstrapForm
34
34
 
35
35
  def form_group_content(label, help_text, options, &block)
36
36
  if group_layout_horizontal?(options[:layout])
37
- concat(label).concat(content_tag(:div, capture(&block) + help_text, class: form_group_control_class(options)))
37
+ concat(label).concat(tag.div(capture(&block) + help_text, class: form_group_control_class(options)))
38
38
  else
39
- concat(label)
39
+ # Floating labels need to be rendered after the field
40
+ concat(label) unless options[:floating]
40
41
  concat(capture(&block))
42
+ concat(label) if options[:floating]
41
43
  concat(help_text) if help_text
42
44
  end
43
45
  end
@@ -50,15 +52,24 @@ module BootstrapForm
50
52
  end
51
53
 
52
54
  def form_group_classes(options)
53
- classes = ["form-group", options[:class].try(:split)].flatten.compact
54
- classes << "row" if group_layout_horizontal?(options[:layout]) && classes.exclude?("form-row")
55
- classes << "form-inline" if field_inline_override?(options[:layout])
55
+ classes = ["mb-3", options[:class].try(:split)].flatten.compact
56
+ classes << "row" if horizontal_group_with_gutters?(options[:layout], classes)
57
+ classes << "col-auto g-3" if field_inline_override?(options[:layout])
56
58
  classes << feedback_class if options[:icon]
59
+ classes << "form-floating" if options[:floating]
57
60
  classes
58
61
  end
59
62
 
63
+ def horizontal_group_with_gutters?(layout, classes)
64
+ group_layout_horizontal?(layout) && !classes_include_gutters?(classes)
65
+ end
66
+
60
67
  def group_layout_horizontal?(layout)
61
68
  get_group_layout(layout) == :horizontal
62
69
  end
70
+
71
+ def classes_include_gutters?(classes)
72
+ classes.any? { |c| c =~ /^g-\d+$/ }
73
+ end
63
74
  end
64
75
  end
@@ -6,7 +6,7 @@ module BootstrapForm
6
6
 
7
7
  private
8
8
 
9
- def form_group_builder(method, options, html_options=nil)
9
+ def form_group_builder(method, options, html_options=nil, &block)
10
10
  no_wrapper = options[:wrapper] == false
11
11
 
12
12
  options = form_group_builder_options(options, method)
@@ -21,16 +21,14 @@ module BootstrapForm
21
21
  if no_wrapper
22
22
  yield
23
23
  else
24
- form_group(method, form_group_options) { yield }
24
+ form_group(method, form_group_options, &block)
25
25
  end
26
26
  end
27
27
 
28
28
  def form_group_builder_options(options, method)
29
29
  options.symbolize_keys!
30
30
  options = convert_form_tag_options(method, options) if acts_like_form_tag
31
- unless options[:skip_label]
32
- options[:required] = form_group_required(options) if options.key?(:skip_required)
33
- end
31
+ options[:required] = form_group_required(options) if !options[:skip_label] && options.key?(:skip_required)
34
32
  options
35
33
  end
36
34
 
@@ -48,7 +46,8 @@ module BootstrapForm
48
46
  id: options[:id], help: options[:help], icon: options[:icon],
49
47
  label_col: options[:label_col], control_col: options[:control_col],
50
48
  add_control_col_class: options[:add_control_col_class],
51
- layout: get_group_layout(options[:layout]), class: options[:wrapper_class]
49
+ layout: get_group_layout(options[:layout]), class: options[:wrapper_class],
50
+ floating: options[:floating]
52
51
  }
53
52
 
54
53
  form_group_options.merge!(wrapper_options) if wrapper_options.is_a?(Hash)
@@ -57,12 +56,11 @@ module BootstrapForm
57
56
  end
58
57
 
59
58
  def form_group_label(options, css_options)
60
- hash = {
59
+ {
61
60
  text: form_group_label_text(options[:label]),
62
61
  class: form_group_label_class(options),
63
62
  required: options[:required]
64
63
  }.merge(css_options[:id].present? ? { for: css_options[:id] } : {})
65
- hash
66
64
  end
67
65
 
68
66
  def form_group_label_text(label)
@@ -14,7 +14,7 @@ module BootstrapForm
14
14
  def primary(name=nil, options={}, &block)
15
15
  setup_css_class "btn btn-primary", options
16
16
 
17
- if options[:render_as_button] || block_given?
17
+ if options[:render_as_button] || block
18
18
  options.except! :render_as_button
19
19
  button(name, options, &block)
20
20
  else
@@ -26,8 +26,8 @@ module BootstrapForm
26
26
  css = options[:class] || "alert alert-danger"
27
27
  return unless object.respond_to?(:errors) && object.errors.full_messages.any?
28
28
 
29
- content_tag :div, class: css do
30
- concat content_tag :p, title
29
+ tag.div class: css do
30
+ concat tag.p title
31
31
  concat error_summary unless options[:error_summary] == false
32
32
  end
33
33
  end
@@ -35,9 +35,9 @@ module BootstrapForm
35
35
  def error_summary
36
36
  return unless object.errors.any?
37
37
 
38
- content_tag :ul, class: "rails-bootstrap-forms-error-summary" do
38
+ tag.ul class: "rails-bootstrap-forms-error-summary" do
39
39
  object.errors.full_messages.each do |error|
40
- concat content_tag(:li, error)
40
+ concat tag.li(error)
41
41
  end
42
42
  end
43
43
  end
@@ -46,8 +46,9 @@ module BootstrapForm
46
46
  return unless error?(name)
47
47
 
48
48
  hide_attribute_name = options[:hide_attribute_name] || false
49
+ custom_class = options[:custom_class] || false
49
50
 
50
- content_tag :div, class: "alert alert-danger" do
51
+ tag.div class: custom_class || "invalid-feedback" do
51
52
  if hide_attribute_name
52
53
  object.errors[name].join(", ")
53
54
  else
@@ -85,7 +86,7 @@ module BootstrapForm
85
86
  input = attach_input(options, :prepend) + input + attach_input(options, :append)
86
87
  input += generate_error(name)
87
88
  options.present? &&
88
- input = content_tag(:div, input, class: ["input-group", options[:input_group_class]].compact)
89
+ input = tag.div(input, class: ["input-group", options[:input_group_class]].compact)
89
90
  input
90
91
  end
91
92
 
@@ -95,9 +96,9 @@ module BootstrapForm
95
96
  end
96
97
 
97
98
  def input_group_content(content)
98
- return content if content =~ /btn/
99
+ return content if /btn/.match?(content)
99
100
 
100
- content_tag(:span, content, class: "input-group-text")
101
+ tag.span(content, class: "input-group-text")
101
102
  end
102
103
 
103
104
  def static_class
@@ -108,7 +109,7 @@ module BootstrapForm
108
109
 
109
110
  def attach_input(options, key)
110
111
  tags = [*options[key]].map do |item|
111
- content_tag(:div, input_group_content(item), class: "input-group-#{key}")
112
+ input_group_content(item)
112
113
  end
113
114
  ActiveSupport::SafeBuffer.new(tags.join)
114
115
  end
@@ -10,7 +10,8 @@ module BootstrapForm
10
10
  define_method "#{field_name}_with_bootstrap" do |name, options={}|
11
11
  form_group_builder(name, options) do
12
12
  prepend_and_append_input(name, options) do
13
- send("#{field_name}_without_bootstrap".to_sym, name, options)
13
+ options[:placeholder] ||= name if options[:floating]
14
+ send("#{field_name}_without_bootstrap".to_sym, name, options.except(:floating))
14
15
  end
15
16
  end
16
17
  end
@@ -19,11 +20,10 @@ module BootstrapForm
19
20
  end
20
21
 
21
22
  def bootstrap_select_group(field_name)
22
- with_field_name = "#{field_name}_with_bootstrap"
23
- without_field_name = "#{field_name}_without_bootstrap"
24
- define_method(with_field_name) do |name, options={}, html_options={}|
23
+ define_method("#{field_name}_with_bootstrap") do |name, options={}, html_options={}|
24
+ html_options = html_options.reverse_merge(control_class: "form-select")
25
25
  form_group_builder(name, options, html_options) do
26
- form_group_content_tag(name, field_name, without_field_name, options, html_options)
26
+ form_group_content_tag(name, field_name, "#{field_name}_without_bootstrap", options, html_options)
27
27
  end
28
28
  end
29
29
 
@@ -10,10 +10,10 @@ module BootstrapForm
10
10
  def check_box_with_bootstrap(name, options={}, checked_value="1", unchecked_value="0", &block)
11
11
  options = options.symbolize_keys!
12
12
  check_box_options = options.except(:class, :label, :label_class, :error_message, :help,
13
- :inline, :custom, :hide_label, :skip_label, :wrapper_class)
13
+ :inline, :hide_label, :skip_label, :wrapper_class, :switch)
14
14
  check_box_options[:class] = check_box_classes(name, options)
15
15
 
16
- content_tag(:div, class: check_box_wrapper_class(options)) do
16
+ tag.div(class: check_box_wrapper_class(options)) do
17
17
  html = check_box_without_bootstrap(name, check_box_options, checked_value, unchecked_value)
18
18
  html.concat(check_box_label(name, options, checked_value, &block)) unless options[:skip_label]
19
19
  html.concat(generate_error(name)) if options[:error_message]
@@ -38,7 +38,7 @@ module BootstrapForm
38
38
  end
39
39
 
40
40
  def check_box_description(name, options, &block)
41
- content = block_given? ? capture(&block) : options[:label]
41
+ content = block ? capture(&block) : options[:label]
42
42
  content || object&.class&.human_attribute_name(name) || name.to_s.humanize
43
43
  end
44
44
 
@@ -50,40 +50,26 @@ module BootstrapForm
50
50
  end
51
51
 
52
52
  def check_box_classes(name, options)
53
- classes = [options[:class]]
54
- classes << (options[:custom] ? "custom-control-input" : "form-check-input")
53
+ classes = Array(options[:class]) << "form-check-input"
55
54
  classes << "is-invalid" if error?(name)
56
55
  classes << "position-static" if options[:skip_label] || options[:hide_label]
57
56
  classes.flatten.compact
58
57
  end
59
58
 
60
59
  def check_box_label_class(options)
61
- classes = []
62
- classes << (options[:custom] ? "custom-control-label" : "form-check-label")
60
+ classes = ["form-check-label"]
63
61
  classes << options[:label_class]
64
62
  classes << hide_class if options[:hide_label]
65
63
  classes.flatten.compact
66
64
  end
67
65
 
68
66
  def check_box_wrapper_class(options)
69
- classes = []
70
- if options[:custom]
71
- classes << custom_check_box_wrapper_class(options)
72
- else
73
- classes << "form-check"
74
- classes << "form-check-inline" if layout_inline?(options[:inline])
75
- end
67
+ classes = ["form-check"]
68
+ classes << "form-check-inline" if layout_inline?(options[:inline])
69
+ classes << "form-switch" if options[:switch]
76
70
  classes << options[:wrapper_class] if options[:wrapper_class].present?
77
71
  classes.flatten.compact
78
72
  end
79
-
80
- def custom_check_box_wrapper_class(options)
81
- classes = []
82
- classes << "custom-control"
83
- classes << (options[:custom] == :switch ? "custom-switch" : "custom-checkbox")
84
- classes << "custom-control-inline" if layout_inline?(options[:inline])
85
- classes
86
- end
87
73
  end
88
74
  end
89
75
  end
@@ -10,6 +10,7 @@ module BootstrapForm
10
10
  # Disabling Metrics/ParameterLists because the upstream Rails method has the same parameters
11
11
  # rubocop:disable Metrics/ParameterLists
12
12
  def collection_select_with_bootstrap(method, collection, value_method, text_method, options={}, html_options={})
13
+ html_options = html_options.reverse_merge(control_class: "form-select")
13
14
  form_group_builder(method, options, html_options) do
14
15
  input_with_error(method) do
15
16
  collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)