bootstrap_form 1.0.0 → 2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 78f6f16a42dc3bd71205a9474b10836f344c76c4
4
+ data.tar.gz: e5ef1c16c2c0fd3a5fc8d1a3ed484d05efcaa383
5
+ SHA512:
6
+ metadata.gz: a877f20198877308837384bd79f1fe6aff438691aa9fda349c557d614ce685dbca69b8b618e39b6a4e486431d793d8a1621308d78ea7ac5daa02337704511b9d
7
+ data.tar.gz: 667fd4a3fc7b7aad50ceb5135590c5eae81ab1c6de25cca47af5904d199b1461b111c1a6ded6c588232db1b8416548fd14a0f150e75a83f206218fe1e9660769
data/README.md CHANGED
@@ -2,90 +2,39 @@
2
2
 
3
3
  # BootstrapForm
4
4
 
5
- **BootstrapForm** is a form builder that makes it super easy to
6
- integrate Twitter Bootstrap-style forms into your Rails App.
5
+ **BootstrapForm** is a rails form builder that makes it super easy to integrate
6
+ twitter bootstrap-style forms into your rails application.
7
7
 
8
8
  ## Requirements
9
9
 
10
10
  * Ruby 1.9+
11
- * Rails 4.0+
12
- * Twitter Bootstrap 2.0+
11
+ * Rails 3+
12
+ * Twitter Bootstrap 3.0+
13
13
 
14
14
  ## Installation
15
15
 
16
16
  Add it to your Gemfile:
17
17
 
18
- ### Rails 4.0+
19
-
20
18
  `gem 'bootstrap_form'`
21
19
 
22
- ### Rails 3.1+
23
-
24
- `gem 'bootstrap_form', '~> 0.3.2'`
25
-
26
-
27
- Run the following command to install it:
20
+ Then:
28
21
 
29
22
  `bundle`
30
23
 
31
- Add this line to app/assets/stylesheets/application.css.scss:
32
-
33
- ```css
34
- /*
35
- *= require bootstrap_form
36
- */
37
- ```
38
-
39
- ## Example
40
-
41
- Here's a quick example to get you started:
42
-
43
- ```erb
44
- <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }, help: :block) do |f| %>
45
- <%= f.alert_message "Please fix the errors below." %>
46
-
47
- <%= f.text_field :twitter_username, prepend: '@', label: 'Twitter' %>
48
- <%= f.text_field :email %>
49
- <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
50
- <%= f.password_field :password_confirmation, label: 'Confirm Password' %>
51
- <%= f.control_group :terms do %>
52
- <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
53
- <% end %>
54
-
55
- <%= f.actions do %>
56
- <%= f.primary 'Create My Account', disable_with: 'Saving...' %>
57
- <% end %>
58
- <% end %>
59
- ```
60
-
61
- Screenshot:
62
-
63
- ![Example form](https://github.com/potenza/bootstrap_form/raw/master/examples/example_form.png)
64
-
65
- Screenshot with errors:
66
-
67
- ![Example form with errors](https://github.com/potenza/bootstrap_form/raw/master/examples/example_form_errors.png)
68
-
69
24
  ## Usage
70
25
 
71
- To get started, just use the **BootstrapForm** form helper:
26
+ To get started, just use the **BootstrapForm** form helper. Here's an example:
72
27
 
73
28
  ```erb
74
29
  <%= bootstrap_form_for(@user) do |f| %>
75
- ...
76
- <% end %>
77
- ```
78
-
79
- To use a horizontal-style form with labels to the left of the inputs,
80
- add the `.form-horizontal` class:
81
-
82
- ```erb
83
- <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
84
- ...
30
+ <%= f.email_field :email %>
31
+ <%= f.password_field :password %>
32
+ <%= f.check_box :remember_me %>
33
+ <%= f.submit "Log In" %>
85
34
  <% end %>
86
35
  ```
87
36
 
88
- ### Form Helpers
37
+ ### Supported Form Helpers
89
38
 
90
39
  This gem wraps the following Rails form helpers:
91
40
 
@@ -105,155 +54,140 @@ This gem wraps the following Rails form helpers:
105
54
  * check_box
106
55
  * radio_button
107
56
 
108
- You can use the helpers like you're used to:
57
+ ### Default Form Style
109
58
 
110
- ```erb
111
- <%= bootstrap_form_for(@user) do |f| %>
112
- <%= f.text_field :email %>
113
- <%= f.password_field :password %>
114
- <%= f.primary "Create My Account" %>
115
- <% end %>
116
- ```
117
-
118
- This gem also wraps checkboxes and radios, which should be placed inside
119
- of a `control_group` to render correctly. The following example ensures
120
- that the entire control group will display an error if an associated
121
- validations fails:
122
-
123
- ```erb
124
- <%= f.control_group :skill_level, label: { text: 'Skill' }, help: 'This is optional' do %>
125
- <%= f.radio_button :skill_level, 0, label: 'Novice', checked: true %>
126
- <%= f.radio_button :skill_level, 1, label: 'Intermediate' %>
127
- <%= f.radio_button :skill_level, 2, label: 'Advanced' %>
128
- <% end %>
59
+ By default, your forms will stack labels on top of controls and your controls
60
+ will grow to 100% of the available width.
129
61
 
130
- <%= f.control_group :terms, label: { text: 'Terms' } do %>
131
- <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
132
- <% end %>
133
- ```
62
+ ### Inline Forms
134
63
 
135
- You can display checkboxes and radios `inline` like this:
64
+ To use an inline-style form, use the `style: :inline` option. To hide labels,
65
+ use the `hide_label: true` option, which keeps your labels accessible to those
66
+ using screen readers.
136
67
 
137
68
  ```erb
138
- <%= f.control_group :skill_level, label: { text: 'Skill' } do %>
139
- <%= f.radio_button :skill_level, 0, label: 'Novice', inline: true %>
140
- <%= f.radio_button :skill_level, 1, label: 'Intermediate', inline: true %>
141
- <%= f.radio_button :skill_level, 2, label: 'Advanced', inline: true %>
69
+ <%= bootstrap_form_for(@user, style: :inline) do |f| %>
70
+ <%= f.email_field :email, hide_label: true %>
71
+ <%= f.password_field :password, hide_label: true %>
72
+ <%= f.check_box :remember_me %>
73
+ <%= f.submit "Log In" %>
142
74
  <% end %>
143
75
  ```
144
76
 
145
- ### Labels
77
+ ### Horizontal Forms
146
78
 
147
- Use the `label` option if you want to specify the field's label text:
148
-
149
- ```erb
150
- <%= f.password_field :password_confirmation, label: 'Confirm Password' %>
151
- ```
79
+ To use a horizontal-style form with labels to the left of the inputs, use the
80
+ `style: :horizontal` option. You should specify both `left` and `right` css
81
+ classes as well (they default to `col-sm-2` and `col-sm-10`).
152
82
 
153
- If you don't want to render the field's label, pass `:none` to the option:
83
+ In the example below, the checkbox and submit button have been wrapped in a
84
+ `form_group` to keep them properly aligned.
154
85
 
155
86
  ```erb
156
- <%= f.text_area :comment, label: :none, placeholder: 'Leave a comment...' %>
87
+ <%= bootstrap_form_for(@user, style: :horizontal, left: "col-sm-2", right: "col-sm-10") do |f| %>
88
+ <%= f.email_field :email %>
89
+ <%= f.password_field :password %>
90
+ <%= f.form_group do %>
91
+ <%= f.check_box :remember_me %>
92
+ <% end %>
93
+ <%= f.form_group do %>
94
+ <%= f.submit "Log In" %>
95
+ <% end %>
96
+ <% end %>
157
97
  ```
158
98
 
159
- NOTE: To specify the label for a `control_group` you must do it like this:
99
+ To create a static control in a horizontal form, use the following markup:
160
100
 
161
101
  ```erb
162
- <%= f.control_group :terms, label: { text: 'Terms' } do %>
163
- <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
102
+ <%= f.form_group :nil, label: { text: "Foo" } do %>
103
+ <p class="form-control-static">
104
+ Bar
105
+ </p>
164
106
  <% end %>
165
107
  ```
166
108
 
167
- ### Help text
109
+ ### Labels
168
110
 
169
- To add help text, use the `help` option, which will place it
170
- to the right of the field:
111
+ Use the `label` option if you want to specify the field's label text:
171
112
 
172
113
  ```erb
173
- <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
114
+ <%= f.password_field :password_confirmation, label: "Confirm Password" %>
174
115
  ```
175
116
 
176
- To place help text underneath a field, pass the option `help:
177
- :block` to the `bootstrap_form_for` helper:
117
+ To hide a label, use the `hide_label: true` option. This adds the `sr-only`
118
+ class, which keeps your labels accessible to those using screen readers.
178
119
 
179
120
  ```erb
180
- <%= bootstrap_form_for(@user, help: :block) do |f| %>
181
- <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
182
- <% end %>
121
+ <%= f.text_area :comment, hide_label: :true, placeholder: "Leave a comment..." %>
183
122
  ```
184
123
 
185
- ### Prepending inputs
124
+ ### Help Text
186
125
 
187
- You can prepend an input file with the `prepend` option:
126
+ To add help text, use the `help` option:
188
127
 
189
128
  ```erb
190
- <%= f.text_field :twitter_username, prepend: '@' %>
129
+ <%= f.password_field :password, help: "Must be at least 6 characters long" %>
191
130
  ```
192
131
 
193
- ### Appending inputs
132
+ ### Submit Buttons
194
133
 
195
- You can append an input file with the `append` option:
134
+ The `btn btn-default` css classes are automatically added to your submit
135
+ buttons.
196
136
 
197
137
  ```erb
198
- <%= f.text_field :amount, append: '.00' %>
138
+ <%= f.submit "Log In" %>
199
139
  ```
200
140
 
201
- ### Submit buttons
202
-
203
- This gem provides a few different options for submit buttons.
204
-
205
- Here's a simple `primary` button (this applies the `.btn` and `.btn-primary` classes):
141
+ You can specify your own classes like this:
206
142
 
207
143
  ```erb
208
- <%= f.primary "Create My Account" %>
144
+ <%= f.submit "Log In", class: "btn btn-primary" %>
209
145
  ```
210
146
 
211
- Here's a `secondary` submit button (applies just the `.btn` class):
147
+ ### Checkboxes and Radios
212
148
 
213
- ```erb
214
- <%= f.secondary "Create My Account" %>
215
- ```
216
-
217
- You can use the `actions` helper, which wraps your submit button in a
218
- `.form-actions` class.
149
+ Checkboxes and radios should be placed inside of a `form_group` to render
150
+ properly. The following example ensures that the entire form group will display
151
+ an error if an associated validations fails:
219
152
 
220
153
  ```erb
221
- <%= f.actions do %>
222
- <%= f.primary 'Create My Account' %>
154
+ <%= f.form_group :skill_level, label: { text: "Skill" }, help: "Optional Help Text" do %>
155
+ <%= f.radio_button :skill_level, 0, label: "Novice", checked: true %>
156
+ <%= f.radio_button :skill_level, 1, label: "Intermediate" %>
157
+ <%= f.radio_button :skill_level, 2, label: "Advanced" %>
158
+ <% end %>
159
+
160
+ <%= f.form_group :terms do %>
161
+ <%= f.check_box :terms, label: "I agree to the Terms of Service" %>
223
162
  <% end %>
224
163
  ```
225
164
 
226
- And if you don't want to use the `actions` helper, here's how you might
227
- style a `primary` button with horizontal-style forms:
165
+ You can also create a checkbox using a block:
228
166
 
229
167
  ```erb
230
- <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
231
- <%= f.control_group do %>
232
- <%= f.primary "Create My Account" %>
168
+ <%= f.form_group :terms, label: { text: "Optional Label" } do %>
169
+ <%= f.check_box :terms do %>
170
+ You need to check this box to accept our terms of service and privacy policy
233
171
  <% end %>
234
172
  <% end %>
235
173
  ```
236
174
 
237
- ### Custom Control Groups
238
-
239
- Sometimes you need to wrap an element in Bootstrap-style markup.
240
- This is mostly needed to align submit buttons when using horizontal-style
241
- forms (also shown above):
175
+ To display checkboxes and radios inline, pass the `inline: true` option:
242
176
 
243
177
  ```erb
244
- <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
245
- <%= f.control_group do %>
246
- <%= f.primary "Create My Account" %>
247
- <% end %>
178
+ <%= f.form_group :skill_level, label: { text: "Skill" } do %>
179
+ <%= f.radio_button :skill_level, 0, label: "Novice", inline: true %>
180
+ <%= f.radio_button :skill_level, 1, label: "Intermediate", inline: true %>
181
+ <%= f.radio_button :skill_level, 2, label: "Advanced", inline: true %>
248
182
  <% end %>
249
183
  ```
250
184
 
251
- To specify a label that isn't linked to an element you can do this:
185
+ ### Prepending and Appending Inputs
186
+
187
+ Pass the `prepend` and/or `append` options to the input field:
252
188
 
253
189
  ```erb
254
- <%= f.control_group :nil, label: { text: 'Foo' } do %>
255
- <span>Bar</span>
256
- <% end %>
190
+ <%= f.text_field :price, prepend: "$", append: ".00" %>
257
191
  ```
258
192
 
259
193
  ### Validation Errors
@@ -262,9 +196,9 @@ When a validation error is triggered, the field will be outlined and the
262
196
  error will be displayed next to the field (or below it if you're using
263
197
  block-style help text). Rails normally wraps fields in a div
264
198
  (field_with_errors), but this behavior is suppressed when
265
- `bootstrap_form_for` is called.
199
+ `bootstrap_form_for` is used.
266
200
 
267
- To display an error message wrapped in `.alert` and `.alert-error`
201
+ To display an error message wrapped in `.alert` and `.alert-danger`
268
202
  classes, you can use the `alert_message` helper:
269
203
 
270
204
  ```erb
@@ -1,6 +1,5 @@
1
1
  require 'bootstrap_form/form_builder'
2
2
  require 'bootstrap_form/helper'
3
- require 'bootstrap_form/engine'
4
3
 
5
4
  module BootstrapForm
6
5
  end
@@ -1,5 +1,7 @@
1
1
  module BootstrapForm
2
2
  class FormBuilder < ActionView::Helpers::FormBuilder
3
+ attr_reader :style, :left_class, :right_class, :has_error
4
+
3
5
  FORM_HELPERS = %w{text_field password_field text_area file_field
4
6
  number_field email_field telephone_field phone_field url_field
5
7
  select collection_select date_select time_select datetime_select}
@@ -8,9 +10,9 @@ module BootstrapForm
8
10
  delegate :capture, to: :@template
9
11
 
10
12
  def initialize(object_name, object, template, options, proc=nil)
11
- help = options.fetch(:help, nil)
12
- @help_class = help.eql?(:block) ? 'help-block' : 'help-inline'
13
-
13
+ @style = options[:style]
14
+ @left_class = (options[:left] || default_left_class) + " control-label"
15
+ @right_class = options[:right] || default_right_class
14
16
  super
15
17
  end
16
18
 
@@ -19,39 +21,31 @@ module BootstrapForm
19
21
  options = args.extract_options!.symbolize_keys!
20
22
 
21
23
  label = options.delete(:label)
22
- help = options.delete(:help)
23
-
24
- control_group(name, label: { text: label }, help: help) do
24
+ label_class = hide_class if options.delete(:hide_label)
25
+ help = options.delete(:help)
25
26
 
27
+ form_group(name, label: { text: label, class: label_class }, help: help) do
28
+ options[:class] = "form-control #{options[:class]}".rstrip
26
29
  args << options.except(:prepend, :append)
27
- element = super(name, *args)
28
-
29
- if prepend = options.delete(:prepend)
30
- element = content_tag(:div, class: 'input-prepend') do
31
- content_tag(:span, prepend, class: 'add-on') + element
32
- end
33
- end
34
-
35
- if append = options.delete(:append)
36
- element = content_tag(:div, class: 'input-append') do
37
- element + content_tag(:span, append, class: 'add-on')
38
- end
39
- end
40
-
41
- element
30
+ input = super(name, *args)
31
+ prepend_and_append_input(input, options[:prepend], options[:append])
42
32
  end
43
33
  end
44
34
  end
45
35
 
46
- def check_box(name, options = {}, checked_value = "1", unchecked_value = "0")
36
+ def check_box(name, options = {}, checked_value = '1', unchecked_value = '0')
47
37
  options = options.symbolize_keys!
48
38
 
49
- html = super(name, options.except(:label, :help, :inline), checked_value, unchecked_value)
50
- html += ' ' + (options[:label] || name.to_s.humanize)
39
+ html = super(name, options.except(:label, :help, :inline), checked_value, unchecked_value)
40
+ html << ' ' + (options[:label] || name.to_s.humanize)
51
41
 
52
- css = 'checkbox'
53
- css << ' inline' if options[:inline]
54
- label(name, html, class: css)
42
+ if options[:inline]
43
+ label(name, html, class: "checkbox-inline")
44
+ else
45
+ content_tag(:div, class: "checkbox") do
46
+ label(name, html)
47
+ end
48
+ end
55
49
  end
56
50
 
57
51
  def radio_button(name, value, *args)
@@ -61,67 +55,79 @@ module BootstrapForm
61
55
  html = super(name, value, *args) + ' ' + options[:label]
62
56
 
63
57
  css = 'radio'
64
- css << ' inline' if options[:inline]
58
+ css << '-inline' if options[:inline]
65
59
  label("#{name}_#{value}", html, class: css)
66
60
  end
67
61
 
68
- def control_group(name = nil, options = {}, &block)
69
- errors_has_name = object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
62
+ def form_group(name = nil, options = {}, &block)
63
+ options[:class] = 'form-group'
64
+ options[:class] << ' has-error' if has_error?(name)
70
65
 
71
- options[:class] ||= 'control-group'
72
- options[:class] << ' error' if errors_has_name
66
+ html = capture(&block)
67
+ html << generate_help(name, options[:help])
68
+ html = content_tag(:div, html, class: right_class) if horizontal?
73
69
 
74
- label = options.delete(:label)
75
- _help = options.delete(:help)
76
-
77
- content_tag(:div, options) do
78
- html = ''
70
+ content_tag(:div, options.except(:label, :help)) do
71
+ "#{generate_label(name, options[:label])}#{html}".html_safe
72
+ end
73
+ end
79
74
 
80
- if label && label[:text] != :none
81
- label[:class] ||= 'control-label'
82
- label[:for] ||= '' if name.nil?
75
+ def submit(name, options = {})
76
+ options.merge! class: 'btn btn-default' unless options.has_key? :class
77
+ super name, options
78
+ end
83
79
 
84
- html << label(name, label[:text], label.except(:text))
85
- end
80
+ def alert_message(title, *args)
81
+ options = args.extract_options!
82
+ css = options[:class] || 'alert alert-danger'
86
83
 
87
- html << content_tag(:div, class: 'controls') do
88
- controls = capture(&block)
84
+ if object.respond_to?(:errors) && object.errors.full_messages.any?
85
+ content_tag :div, title, class: css
86
+ end
87
+ end
89
88
 
90
- help = errors_has_name ? object.errors[name].join(', ') : _help
91
- controls << content_tag(:span, help, class: @help_class) if help
89
+ private
92
90
 
93
- controls.html_safe
94
- end
91
+ def horizontal?
92
+ style == :horizontal
93
+ end
95
94
 
96
- html.html_safe
97
- end
95
+ def default_left_class
96
+ "col-sm-2"
98
97
  end
99
98
 
100
- def actions(&block)
101
- content_tag :div, class: "form-actions" do
102
- capture(&block)
103
- end
99
+ def default_right_class
100
+ "col-sm-10"
104
101
  end
105
102
 
106
- def primary(name, options = {})
107
- options.merge! class: 'btn btn-primary'
108
- submit name, options
103
+ def hide_class
104
+ "sr-only" # still accessible for screen readers
109
105
  end
110
106
 
111
- def secondary(name, options = {})
112
- options.merge! class: 'btn'
113
- submit name, options
107
+ def has_error?(name)
108
+ object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
114
109
  end
115
110
 
116
- def alert_message(title, *args)
117
- options = args.extract_options!
118
- css = options[:class] || "alert alert-error"
111
+ def prepend_and_append_input(input, prepend, append)
112
+ input = content_tag(:span, prepend, class: 'input-group-addon') + input if prepend
113
+ input << content_tag(:span, append, class: 'input-group-addon') if append
114
+ input = content_tag(:div, input, class: 'input-group') if prepend || append
115
+ input
116
+ end
119
117
 
120
- if object.respond_to?(:errors) && object.errors.full_messages.any?
121
- content_tag :div, class: css do
122
- title
123
- end
118
+ def generate_label(name, options)
119
+ if options
120
+ options[:class] = "#{options[:class]} #{left_class}".lstrip if horizontal?
121
+ label(name, options[:text], options.except(:text))
122
+ elsif horizontal?
123
+ # no label. create an empty one to keep proper form alignment.
124
+ content_tag(:label, "", class: left_class)
124
125
  end
125
126
  end
127
+
128
+ def generate_help(name, help_text)
129
+ help_text = object.errors[name].join(', ') if has_error?(name)
130
+ content_tag(:span, help_text, class: 'help-block') if help_text
131
+ end
126
132
  end
127
133
  end