File: form_builder.rb

package info (click to toggle)
ruby-bootstrap-form 5.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 512 kB
  • sloc: ruby: 1,350; makefile: 4
file content (132 lines) | stat: -rw-r--r-- 4,782 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# require 'bootstrap_form/aliasing'

module BootstrapForm
  class FormBuilder < ActionView::Helpers::FormBuilder
    attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors,
                :label_errors, :acts_like_form_tag

    include BootstrapForm::Helpers::Field
    include BootstrapForm::Helpers::Bootstrap

    include BootstrapForm::FormGroupBuilder
    include BootstrapForm::FormGroup
    include BootstrapForm::Components

    include BootstrapForm::Inputs::Base
    include BootstrapForm::Inputs::CheckBox
    include BootstrapForm::Inputs::CollectionCheckBoxes
    include BootstrapForm::Inputs::CollectionRadioButtons
    include BootstrapForm::Inputs::CollectionSelect
    include BootstrapForm::Inputs::ColorField
    include BootstrapForm::Inputs::DateField
    include BootstrapForm::Inputs::DateSelect
    include BootstrapForm::Inputs::DatetimeField
    include BootstrapForm::Inputs::DatetimeLocalField
    include BootstrapForm::Inputs::DatetimeSelect
    include BootstrapForm::Inputs::EmailField
    include BootstrapForm::Inputs::FileField
    include BootstrapForm::Inputs::GroupedCollectionSelect
    include BootstrapForm::Inputs::MonthField
    include BootstrapForm::Inputs::NumberField
    include BootstrapForm::Inputs::PasswordField
    include BootstrapForm::Inputs::PhoneField
    include BootstrapForm::Inputs::RadioButton
    include BootstrapForm::Inputs::RangeField
    include BootstrapForm::Inputs::RichTextArea
    include BootstrapForm::Inputs::SearchField
    include BootstrapForm::Inputs::Select
    include BootstrapForm::Inputs::Submit
    include BootstrapForm::Inputs::TelephoneField
    include BootstrapForm::Inputs::TextArea
    include BootstrapForm::Inputs::TextField
    include BootstrapForm::Inputs::TimeField
    include BootstrapForm::Inputs::TimeSelect
    include BootstrapForm::Inputs::TimeZoneSelect
    include BootstrapForm::Inputs::UrlField
    include BootstrapForm::Inputs::WeekField

    include ActionView::Helpers::OutputSafetyHelper

    delegate :content_tag, :capture, :concat, :tag, to: :@template

    def initialize(object_name, object, template, options)
      warn_deprecated_layout_value(options)
      @layout = options[:layout] || default_layout
      @label_col = options[:label_col] || default_label_col
      @control_col = options[:control_col] || default_control_col
      @label_errors = options[:label_errors] || false
      @inline_errors = options[:inline_errors].nil? ? @label_errors != true : options[:inline_errors] != false
      @acts_like_form_tag = options[:acts_like_form_tag]
      add_default_form_attributes_and_form_inline options
      super
    end

    def add_default_form_attributes_and_form_inline(options)
      options[:html] ||= {}
      options[:html].reverse_merge!(BootstrapForm.config.default_form_attributes)

      return unless options[:layout] == :inline

      options[:html][:class] =
        safe_join(([*options[:html][:class]&.split(/\s+/)] + %w[row row-cols-auto g-3 align-items-center])
        .compact.uniq, " ")
    end

    def fields_for_with_bootstrap(record_name, record_object=nil, fields_options={}, &block)
      fields_options = fields_for_options(record_object, fields_options)
      record_object = nil if record_object.is_a?(Hash) && record_object.extractable_options?
      fields_for_without_bootstrap(record_name, record_object, fields_options, &block)
    end

    bootstrap_alias :fields_for

    # the Rails `fields` method passes its options
    # to the builder, so there is no need to write a `bootstrap_form` helper
    # for the `fields` method.

    private

    def fields_for_options(record_object, fields_options)
      field_options = fields_options
      field_options = record_object if record_object.is_a?(Hash) && record_object.extractable_options?
      %i[layout control_col inline_errors label_errors].each do |option|
        field_options[option] ||= options[option]
      end
      field_options[:label_col] = field_options[:label_col].present? ? (field_options[:label_col]).to_s : options[:label_col]
      field_options
    end

    def default_layout
      # :vertical, :horizontal or :inline
      :vertical
    end

    def default_label_col
      "col-sm-2"
    end

    def offset_col(label_col)
      [*label_col].flat_map { |s| s.split(/\s+/) }.grep(/^col-/).join(" ").gsub(/\bcol-(\w+)-(\d)\b/, 'offset-\1-\2')
    end

    def default_control_col
      "col-sm-10"
    end

    def hide_class
      "visually-hidden" # still accessible for screen readers
    end

    def control_class
      "form-control"
    end

    def feedback_class
      "has-feedback"
    end

    def control_specific_class(method)
      "rails-bootstrap-forms-#{method.to_s.tr('_', '-')}"
    end
  end
end