bootstrap_form 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,45 +1,84 @@
1
- bootstrap_form
2
- ==============
1
+ # BootstrapForm
3
2
 
4
- bootstrap_form is a rails form builder that makes it super easy to create beautiful-looking forms using Twitter Bootstrap 2.0
3
+ **BootstrapForm** is a form builder that makes it super easy to
4
+ integrate Twitter Bootstrap-style forms into your Rails App.
5
5
 
6
-
7
- Requirements
8
- ------------
6
+ ## Requirements
9
7
 
10
8
  * Ruby 1.9+
11
9
  * Rails 3.1+
12
10
  * Twitter Bootstrap 2.0+
13
11
 
12
+ ## Installation
13
+
14
+ Add it to your Gemfile:
15
+
16
+ `gem 'bootstrap_form'`
17
+
18
+ Run the following command to install it:
19
+
20
+ `bundle`
21
+
22
+ Add this line to app/assets/stylesheets/application.css.scss:
23
+
24
+ ```css
25
+ /*
26
+ *= require bootstrap_form
27
+ */
28
+ ```
29
+
30
+ ## Example
14
31
 
15
- Installation
16
- ------------
32
+ Here's a quick example to get you started:
17
33
 
18
- Add the gem to your Gemfile
34
+ ```erb
35
+ <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }, help: :block) do |f| %>
36
+ <%= f.alert_message "Please fix the errors below." %>
19
37
 
20
- gem 'bootstrap_form'
38
+ <%= f.text_field :twitter_username, prepend: '@', label: 'Twitter' %>
39
+ <%= f.text_field :email %>
40
+ <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
41
+ <%= f.password_field :password_confirmation, label: 'Confirm Password' %>
42
+ <%= f.control_group :terms do %>
43
+ <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
44
+ <% end %>
21
45
 
22
- Install the gem
46
+ <%= f.actions do %>
47
+ <%= f.primary 'Create My Account', disable_with: 'Saving...' %>
48
+ <% end %>
49
+ <% end %>
50
+ ```
23
51
 
24
- bundle
52
+ Screenshot:
25
53
 
26
- Add bootstrap_form to your application.css file
54
+ ![Example form](https://github.com/potenza/bootstrap_form/raw/master/examples/example_form.png)
27
55
 
28
- /*
29
- *= require bootstrap_form
30
- */
56
+ Screenshot with errors:
57
+
58
+ ![Example form with errors](https://github.com/potenza/bootstrap_form/raw/master/examples/example_form_errors.png)
31
59
 
32
- This brings in a couple of minor css classes that help format helper and
33
- error messages.
60
+ ## Usage
61
+
62
+ To get started, just use the **BootstrapForm** form helper:
63
+
64
+ ```erb
65
+ <%= bootstrap_form_for(@user) do |f| %>
66
+ ...
67
+ <% end %>
68
+ ```
69
+
70
+ To use a horizontal-style form with labels to the left of the inputs,
71
+ add the `.form-horizontal` class:
34
72
 
35
- Usage
36
- -----
73
+ ```erb
74
+ <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
75
+ ...
76
+ <% end %>
77
+ ```
37
78
 
38
- <%= bootstrap_form_for(@user) do |f| %>
39
- ...
40
- <% end %>
79
+ ### Form Helpers
41
80
 
42
- This plugin provides the following form helpers:
81
+ This gem wraps the following Rails form helpers:
43
82
 
44
83
  * text_field
45
84
  * password_field
@@ -47,7 +86,7 @@ This plugin provides the following form helpers:
47
86
  * file_field
48
87
  * number_field
49
88
  * email_field
50
- * telephone_field (phone_field)
89
+ * telephone_field / phone_field
51
90
  * url_field
52
91
  * select
53
92
  * collection_select
@@ -55,86 +94,160 @@ This plugin provides the following form helpers:
55
94
  * time_select
56
95
  * datetime_select
57
96
  * check_box
97
+ * radio_button
58
98
 
59
- These form helpers accept the same options as the Rails form helpers with the
60
- addition of the options `label`, `help`, and `prepend`. Here's an example form
61
- that also uses the `actions` helper for the submit button:
99
+ You can use the helpers like you're used to:
62
100
 
63
- <%= bootstrap_form_for(@user) do |f| %>
64
- <%= f.alert_message "Please fix the errors below." %>
101
+ ```erb
102
+ <%= bootstrap_form_for(@user) do |f| %>
103
+ <%= f.text_field :email %>
104
+ <%= f.password_field :password %>
105
+ <%= f.primary "Create My Account" %>
106
+ <% end %>
107
+ ```
65
108
 
66
- <%= f.text_field :email, autofocus: :true %>
67
- <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
68
- <%= f.password_field :password_confirmation, label: 'Confirm Password' %>
69
- <%= f.text_field :website, prepend: 'http://' %>
70
- <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
109
+ This gem also wraps checkboxes and radios, which should be placed inside
110
+ of a `control_group` to render correctly. The following example ensures
111
+ that the entire control group will display an error if an associated
112
+ validations fails:
71
113
 
72
- <%= f.actions do %>
73
- <%= f.primary 'Sign Up', disable_with: 'Saving...' %>
74
- <% end %>
75
- <% end %>
114
+ ```erb
115
+ <%= f.control_group :skill_level, label: { text: 'Skill' } do %>
116
+ <%= f.radio_button :skill_level, 0, label: 'Novice', checked: true %>
117
+ <%= f.radio_button :skill_level, 1, label: 'Intermediate' %>
118
+ <%= f.radio_button :skill_level, 2, label: 'Advanced' %>
119
+ <% end %>
76
120
 
77
- ![Example Form](https://github.com/potenza/bootstrap_form/raw/master/examples/example_form.png)
121
+ <%= f.control_group :terms, label: { text: 'Terms' } do %>
122
+ <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
123
+ <% end %>
124
+ ```
78
125
 
126
+ You can display checkboxes and radios `inline` like this:
79
127
 
80
- Options
81
- -------
128
+ ```erb
129
+ <%= f.control_group :skill_level, label: { text: 'Skill' } do %>
130
+ <%= f.radio_button :skill_level, 0, label: 'Novice', inline: true %>
131
+ <%= f.radio_button :skill_level, 1, label: 'Intermediate', inline: true %>
132
+ <%= f.radio_button :skill_level, 2, label: 'Advanced', inline: true %>
133
+ <% end %>
134
+ ```
82
135
 
83
- To use a horizontal-style form with labels to the left of the inputs,
84
- add the `.form-horizontal` class:
136
+ ### Labels
85
137
 
86
- <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
138
+ Use the `label` option if you want to specify the field's label text:
87
139
 
88
- To place helper text underneath the fields, pass the option `help:
89
- :block`:
140
+ ```erb
141
+ <%= f.password_field :password_confirmation, label: 'Confirm Password' %>
142
+ ```
90
143
 
91
- <%= bootstrap_form_for(@user, help: block) do |f| %>
144
+ NOTE: To specify the label for a `control_group` you must do it like this:
92
145
 
93
- Here's an example of a horizontal-style form with block helpers:
146
+ ```erb
147
+ <%= f.control_group :terms, label: { text: 'Terms' } do %>
148
+ <%= f.check_box :terms, label: 'I agree to the Terms of Service' %>
149
+ <% end %>
150
+ ```
94
151
 
95
- ![Example Form](https://github.com/potenza/bootstrap_form/raw/master/examples/example_horizontal_block_form.png)
152
+ ### Help text
96
153
 
154
+ To add help text, use the `help` option, which will place it
155
+ to the right of the field:
97
156
 
98
- Custom Controls
99
- ---------------
157
+ ```erb
158
+ <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
159
+ ```
100
160
 
101
- If you have a custom form control or content that you want to wrap
102
- in Bootstrap-style form markup, you can do the following:
103
-
104
- <%= f.control_group "Custom Field" do %>
105
- <span>My Custom Field</span>
106
- <% end %>
161
+ To place help text underneath a field, pass the option `help:
162
+ :block` to the `bootstrap_form_for` helper:
107
163
 
108
- which will output the following:
164
+ ```erb
165
+ <%= bootstrap_form_for(@user, help: :block) do |f| %>
166
+ <%= f.password_field :password, help: 'Must be at least 6 characters long' %>
167
+ <% end %>
168
+ ```
109
169
 
110
- <div class="control-group">
111
- <label class="control-label">Custom Field</label>
112
- <div class="controls">
113
- <span>My Custom Field</span>
114
- </div>
115
- </div>
170
+ ### Prepending inputs
116
171
 
117
- You can also specify the label's for attribute like this:
172
+ You can prepend an input file with the `prepend` option:
118
173
 
119
- <%= f.control_group "Custom Field", for: 'custom-control' do %>
120
- <span>My Custom Field</span>
121
- <% end %>
122
-
174
+ ```erb
175
+ <%= f.text_field :twitter_username, prepend: '@' %>
176
+ ```
123
177
 
124
- Validation Errors
125
- -----------------
178
+ ### Submit buttons
126
179
 
127
- When a validation error is triggered, the field will be outlined and the
128
- error will be displayed next to the field. Rails normally wraps fields
129
- in a div (field_with_errors), but this behavior is suppressed when `bootstrap_form_for` is called.
180
+ This gem provides a few different options for submit buttons.
181
+
182
+ You can use the `actions` helper, which wraps your submit button in a
183
+ `.form-actions` class.
184
+
185
+ ```erb
186
+ <%= f.actions do %>
187
+ <%= f.primary 'Create My Account' %>
188
+ <% end %>
189
+ ```
190
+
191
+ Here's a simple `primary` button (this applies the `.btn` and `.btn-primary` classes):
192
+
193
+ ```erb
194
+ <%= f.primary "Create My Account" %>
195
+ ```
196
+
197
+ Here's a `secondary` submit button (applies just the `.btn` class):
198
+
199
+ ```erb
200
+ <%= f.secondary "Create My Account" %>
201
+ ```
202
+
203
+ And if you don't want to use the `actions` helper, here's how you might
204
+ style a `primary` button with horizontal-style forms:
130
205
 
131
- ![Example form with errors](https://github.com/potenza/bootstrap_form/raw/master/examples/example_form_error.png)
206
+ ```erb
207
+ <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
208
+ <%= f.control_group do %>
209
+ <%= f.primary "Create My Account" %>
210
+ <% end %>
211
+ <% end %>
212
+ ```
213
+
214
+ ### Custom Control Groups
215
+
216
+ Sometimes you need to wrap a custom control in Bootstrap-style markup.
217
+ This is mostly needed when using horizontal-style forms. You can use the
218
+ `control_group` helper to do this:
219
+
220
+ ```erb
221
+ <%= bootstrap_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
222
+ <%= f.control_group do %>
223
+ <%= f.primary "Create My Account" %>
224
+ <% end %>
225
+ <% end %>
226
+ ```
227
+
228
+ To specify a label that isn't linked to an element you can do this:
229
+
230
+ ```erb
231
+ <%= f.control_group :nil, label: { text: 'Foo' } do %>
232
+ <span>Bar</span>
233
+ <% end %>
234
+ ```
235
+
236
+ ### Validation Errors
237
+
238
+ When a validation error is triggered, the field will be outlined and the
239
+ error will be displayed next to the field (or below it if you're using
240
+ block-style help text). Rails normally wraps fields in a div
241
+ (field_with_errors), but this behavior is suppressed when
242
+ `bootstrap_form_for` is called.
132
243
 
244
+ To display an error message wrapped in `.alert` and `.alert-error`
245
+ classes, you can use the `alert_message` helper:
133
246
 
134
- Credits
135
- -------
247
+ ```erb
248
+ <%= f.alert_message "Please fix the errors below." %>
249
+ ```
136
250
 
137
- Inspired by Ryan Bates' [Form Builder
138
- Railscast](http://railscasts.com/episodes/311-form-builders)
251
+ ## Credits
139
252
 
140
- bootstrap_form is Copyright (c) 2012 Stephen Potenza and is distributed under the MIT license.
253
+ bootstrap_form is Copyright (c) 2013 Stephen Potenza (https://github.com/potenza) and is distributed under the MIT license.
@@ -18,45 +18,66 @@ module BootstrapForm
18
18
  FORM_HELPERS.each do |method_name|
19
19
  define_method(method_name) do |name, *args|
20
20
  options = args.extract_options!.symbolize_keys!
21
- content_tag :div, class: "control-group#{(' error' if object.errors[name].any?)}" do
22
- label(name, options[:label], class: 'control-label') +
23
- content_tag(:div, class: 'controls') do
24
- help = object.errors[name].any? ? object.errors[name].join(', ') : options[:help]
25
- help = content_tag(@help_tag, class: @help_css) { help } if help
26
-
27
- args << options.except(:label, :help, :prepend)
28
- element = super(name, *args) + help
29
-
30
- if prepend = options.delete(:prepend)
31
- element = content_tag(:div, class: 'input-prepend') do
32
- content_tag(:span, prepend, class: 'add-on') + element
33
- end
34
- end
35
21
 
36
- element
22
+ control_group(name, label: { text: options[:label] }) do
23
+ help = object.errors[name].any? ? object.errors[name].join(', ') : options[:help]
24
+ help = content_tag(@help_tag, class: @help_css) { help } if help
25
+
26
+ args << options.except(:label, :help, :prepend)
27
+ element = super(name, *args) + help
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
37
33
  end
34
+
35
+ element
38
36
  end
39
37
  end
40
38
  end
41
39
 
42
40
  def check_box(name, *args)
43
41
  options = args.extract_options!.symbolize_keys!
44
- content_tag :div, class: "control-group#{(' error' if object.errors[name].any?)}" do
45
- content_tag(:div, class: 'controls') do
46
- args << options.except(:label, :help)
47
- html = super(name, *args) + ' ' + options[:label]
48
- label(name, html, class: 'checkbox')
49
- end
50
- end
42
+ args << options.except(:label, :help, :inline)
43
+
44
+ html = super(name, *args) + ' ' + options[:label]
45
+
46
+ css = 'checkbox'
47
+ css << ' inline' if options[:inline]
48
+ label(name, html, class: css)
49
+ end
50
+
51
+ def radio_button(name, value, *args)
52
+ options = args.extract_options!.symbolize_keys!
53
+ args << options.except(:label, :help, :inline)
54
+
55
+ html = super(name, value, *args) + ' ' + options[:label]
56
+
57
+ css = 'radio'
58
+ css << ' inline' if options[:inline]
59
+ label("#{name}_#{value}", html, class: css)
51
60
  end
52
61
 
53
- def control_group(label_name, label_options = {}, &block)
54
- content_tag :div, class: "control-group" do
55
- label_options[:class] = 'control-label'
56
- content_tag(:label, label_name, label_options).html_safe +
57
- content_tag(:div, class: 'controls') do
62
+ def control_group(name = nil, options = {}, &block)
63
+ options[:class] ||= 'control-group'
64
+ options[:class] << ' error' if name && object.errors[name].any?
65
+
66
+ content_tag(:div, options.except(:label)) do
67
+ html = ''
68
+
69
+ if attrs = options.delete(:label)
70
+ attrs[:class] ||= 'control-label'
71
+ attrs[:for] ||= '' if name.nil?
72
+
73
+ html << label(name, attrs[:text], attrs.except(:text))
74
+ end
75
+
76
+ html << content_tag(:div, class: 'controls') do
58
77
  block.call.html_safe
59
78
  end
79
+
80
+ html.html_safe
60
81
  end
61
82
  end
62
83
 
@@ -68,7 +89,11 @@ module BootstrapForm
68
89
 
69
90
  def primary(name, options = {})
70
91
  options.merge! class: 'btn btn-primary'
92
+ submit name, options
93
+ end
71
94
 
95
+ def secondary(name, options = {})
96
+ options.merge! class: 'btn'
72
97
  submit name, options
73
98
  end
74
99
 
@@ -1,3 +1,3 @@
1
1
  module BootstrapForm
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -104,11 +104,26 @@ class BootstrapFormTest < ActionView::TestCase
104
104
  end
105
105
  end
106
106
 
107
- test "check_boxes are wrapped correctly" do
108
- expected = %{<div class=\"control-group\"><div class=\"controls\"><label class=\"checkbox\" for=\"user_misc\"><input name=\"user[misc]\" type=\"hidden\" value=\"0\" /><input id=\"user_misc\" name=\"user[misc]\" type=\"checkbox\" value=\"1\" /> This is a checkbox</label></div></div>}
107
+ test "check_box is wrapped correctly" do
108
+ expected = %{<label class=\"checkbox\" for=\"user_misc\"><input name=\"user[misc]\" type=\"hidden\" value=\"0\" /><input id=\"user_misc\" name=\"user[misc]\" type=\"checkbox\" value=\"1\" /> This is a checkbox</label>}
109
109
  assert_equal expected, @builder.check_box(:misc, label: 'This is a checkbox')
110
110
  end
111
111
 
112
+ test "check_box inline label is setted correctly" do
113
+ expected = %{<label class=\"checkbox inline\" for=\"user_misc\"><input name=\"user[misc]\" type=\"hidden\" value=\"0\" /><input id=\"user_misc\" name=\"user[misc]\" type=\"checkbox\" value=\"1\" /> This is a checkbox</label>}
114
+ assert_equal expected, @builder.check_box(:misc, label: 'This is a checkbox', inline: true)
115
+ end
116
+
117
+ test "radio_button is wrapped correctly" do
118
+ expected = %{<label class=\"radio\" for=\"user_misc_1\"><input id=\"user_misc_1\" name=\"user[misc]\" type=\"radio\" value=\"1\" /> This is a radio button</label>}
119
+ assert_equal expected, @builder.radio_button(:misc, '1', label: 'This is a radio button')
120
+ end
121
+
122
+ test "radio_button inline label is setted correctly" do
123
+ expected = %{<label class=\"radio inline\" for=\"user_misc_1\"><input id=\"user_misc_1\" name=\"user[misc]\" type=\"radio\" value=\"1\" /> This is a radio button</label>}
124
+ assert_equal expected, @builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true)
125
+ end
126
+
112
127
  test "changing the label text" do
113
128
  expected = %{<div class=\"control-group\"><label class=\"control-label\" for=\"user_email\">Email Address</label><div class=\"controls\"><input id=\"user_email\" name=\"user[email]\" size=\"30\" type=\"text\" value=\"steve@example.com\" /></div></div>}
114
129
  assert_equal expected, @builder.text_field(:email, label: 'Email Address')
@@ -130,18 +145,68 @@ class BootstrapFormTest < ActionView::TestCase
130
145
  end
131
146
 
132
147
  test "control_group creates a valid structure and allows arbitrary html to be added via a block" do
133
- output = @builder.control_group "Custom Control" do
148
+ output = @builder.control_group do
134
149
  '<span>custom control here</span>'
135
150
  end
136
- expected = %{<div class="control-group"><label class="control-label">Custom Control</label><div class="controls"><span>custom control here</span></div></div>}
151
+
152
+ expected = %{<div class="control-group"><div class="controls"><span>custom control here</span></div></div>}
137
153
  assert_equal expected, output
138
154
  end
139
155
 
140
- test "control_group allows for the label's 'for' attribute to be set" do
141
- output = @builder.control_group "Custom Control", for: 'custom_control' do
156
+ test "control_group renders the options for div.control_group" do
157
+ output = @builder.control_group nil, id: 'foo' do
142
158
  '<span>custom control here</span>'
143
159
  end
144
- expected = %{<div class="control-group"><label class="control-label" for="custom_control">Custom Control</label><div class="controls"><span>custom control here</span></div></div>}
160
+
161
+ expected = %{<div class="control-group" id="foo"><div class="controls"><span>custom control here</span></div></div>}
162
+ assert_equal expected, output
163
+ end
164
+
165
+ test "control_group overrides the control-group class if another is passed" do
166
+ output = @builder.control_group nil, class: 'foo' do
167
+ '<span>custom control here</span>'
168
+ end
169
+
170
+ expected = %{<div class="foo"><div class="controls"><span>custom control here</span></div></div>}
171
+ assert_equal expected, output
172
+ end
173
+
174
+ test "control_group renders the label correctly" do
175
+ output = @builder.control_group :email, label: { text: 'Custom Control' } do
176
+ '<span>custom control here</span>'
177
+ end
178
+
179
+ expected = %{<div class="control-group"><label class="control-label" for="user_email">Custom Control</label><div class="controls"><span>custom control here</span></div></div>}
180
+ assert_equal expected, output
181
+ end
182
+
183
+ test "control_group overrides the label's 'class' and 'for' attributes if others are passed" do
184
+ output = @builder.control_group nil, label: { text: 'Custom Control', class: 'foo', for: 'bar' } do
185
+ '<span>custom control here</span>'
186
+ end
187
+
188
+ expected = %{<div class="control-group"><label class="foo" for="bar">Custom Control</label><div class="controls"><span>custom control here</span></div></div>}
189
+ assert_equal expected, output
190
+ end
191
+
192
+ test "control_group label's 'for' attribute should be empty if no name was passed" do
193
+ output = @builder.control_group nil, label: { text: 'Custom Control' } do
194
+ '<span>custom control here</span>'
195
+ end
196
+
197
+ expected = %{<div class="control-group"><label class="control-label" for="">Custom Control</label><div class="controls"><span>custom control here</span></div></div>}
198
+ assert_equal expected, output
199
+ end
200
+
201
+ test 'control_group renders the "error" class corrrectly when object is invalid' do
202
+ @user.email = nil
203
+ @user.valid?
204
+
205
+ output = @builder.control_group :email do
206
+ '<span>custom control here</span>'
207
+ end
208
+
209
+ expected = %{<div class="control-group error"><div class="controls"><span>custom control here</span></div></div>}
145
210
  assert_equal expected, output
146
211
  end
147
212
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootstrap_form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-04 00:00:00.000000000 Z
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails