bootstrap_forms 1.0.5 → 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.
- data/.gitignore +3 -0
- data/.travis.yml +4 -0
- data/Guardfile +7 -0
- data/Rakefile +18 -1
- data/bootstrap_forms.gemspec +8 -1
- data/lib/bootstrap_forms.rb +9 -1
- data/lib/bootstrap_forms/engine.rb +12 -2
- data/lib/bootstrap_forms/form_builder.rb +28 -84
- data/lib/bootstrap_forms/helpers.rb +7 -0
- data/lib/bootstrap_forms/{initializer.rb → helpers/form_helper.rb} +7 -9
- data/lib/bootstrap_forms/helpers/form_tag_helper.rb +76 -0
- data/lib/bootstrap_forms/helpers/wrappers.rb +92 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +5 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/projects_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/projects_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/milestone.rb +3 -0
- data/spec/dummy/app/models/project.rb +4 -0
- data/spec/dummy/app/models/task.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +11 -0
- data/spec/dummy/app/views/projects/new.html.erb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +42 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +27 -0
- data/spec/dummy/config/environments/production.rb +54 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +59 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20110710143903_initial_tables.rb +23 -0
- data/spec/dummy/db/schema.rb +29 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/test/functional/projects_controller_test.rb +7 -0
- data/spec/dummy/test/unit/helpers/projects_helper_test.rb +4 -0
- data/spec/dummy/tmp/cache/.gitkeep +0 -0
- data/spec/lib/bootstrap_forms/form_builder_spec.rb +180 -0
- data/spec/spec_helper.rb +20 -0
- metadata +198 -6
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Guardfile
ADDED
data/Rakefile
CHANGED
@@ -1 +1,18 @@
|
|
1
|
-
require 'bundler/gem_tasks'
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
desc 'Default: run specs.'
|
5
|
+
task :default => :spec
|
6
|
+
|
7
|
+
desc "Run specs"
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
10
|
+
# Put spec opts in a file named .rspec in root
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Generate code coverage"
|
14
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
15
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
16
|
+
t.rcov = true
|
17
|
+
t.rcov_opts = ['--exclude', 'spec']
|
18
|
+
end
|
data/bootstrap_forms.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "bootstrap_forms"
|
6
|
-
s.version = "
|
6
|
+
s.version = "2.0.0"
|
7
7
|
s.author = "Seth Vargo"
|
8
8
|
s.email = "sethvargo@gmail.com"
|
9
9
|
s.homepage = "https://github.com/sethvargo/bootstrap_forms"
|
@@ -14,4 +14,11 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
16
|
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_development_dependency "rspec-rails", "~> 2.9.0"
|
19
|
+
s.add_development_dependency "capybara", "~> 1.1.0"
|
20
|
+
s.add_development_dependency "rake"
|
21
|
+
s.add_development_dependency "rails", "~> 3.2.0"
|
22
|
+
s.add_development_dependency "guard-rspec"
|
23
|
+
s.add_development_dependency "sqlite3"
|
17
24
|
end
|
data/lib/bootstrap_forms.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
module BootstrapForms
|
2
2
|
class Engine < ::Rails::Engine
|
3
|
-
|
4
|
-
|
3
|
+
initializer 'bootstrap_forms.initialize' do
|
4
|
+
config.to_prepare do
|
5
|
+
ActiveSupport.on_load(:action_view) do
|
6
|
+
include BootstrapForms::Helpers::FormHelper
|
7
|
+
include BootstrapForms::Helpers::FormTagHelper
|
8
|
+
|
9
|
+
# Do not wrap errors in the extra div
|
10
|
+
::ActionView::Base.field_error_proc = Proc.new do |html_tag, instance_tag|
|
11
|
+
html_tag
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
5
15
|
end
|
6
16
|
end
|
7
17
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module BootstrapForms
|
2
|
-
class FormBuilder < ActionView::Helpers::FormBuilder
|
2
|
+
class FormBuilder < ::ActionView::Helpers::FormBuilder
|
3
|
+
include BootstrapForms::Helpers::Wrappers
|
4
|
+
|
3
5
|
delegate :content_tag, :hidden_field_tag, :check_box_tag, :radio_button_tag, :button_tag, :link_to, :to => :@template
|
4
6
|
|
5
7
|
def error_messages
|
@@ -17,7 +19,7 @@ module BootstrapForms
|
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
%w(collection_select select email_field file_field number_field password_field phone_field range_field search_field telephone_field text_area text_field url_field).each do |method_name|
|
22
|
+
%w(collection_select select country_select time_zone_select email_field file_field number_field password_field phone_field range_field search_field telephone_field text_area text_field url_field).each do |method_name|
|
21
23
|
define_method(method_name) do |name, *args|
|
22
24
|
@name = name
|
23
25
|
@field_options = args.extract_options!
|
@@ -39,16 +41,16 @@ module BootstrapForms
|
|
39
41
|
control_group_div do
|
40
42
|
input_div do
|
41
43
|
label(@name, :class => [ 'checkbox', required_class ].compact.join(' ')) do
|
42
|
-
extras { super(name, *(@args << @field_options)) + human_attribute_name }
|
44
|
+
extras { super(name, *(@args << @field_options)) + (@field_options[:label].blank? ? human_attribute_name : @field_options[:label])}
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def radio_buttons(name, values={}, opts={})
|
50
|
+
def radio_buttons(name, values = {}, opts = {})
|
49
51
|
@name = name
|
50
52
|
@options = opts
|
51
|
-
|
53
|
+
@field_options = opts
|
52
54
|
control_group_div do
|
53
55
|
label_field + input_div do
|
54
56
|
values.map do |text, value|
|
@@ -91,7 +93,7 @@ module BootstrapForms
|
|
91
93
|
content_tag(:div, :class => 'controls') do
|
92
94
|
records.collect do |record|
|
93
95
|
element_id = "#{object_name}_#{attribute}_#{record.send(record_id)}"
|
94
|
-
radiobutton = radio_button_tag("#{object_name}[#{attribute}]
|
96
|
+
radiobutton = radio_button_tag("#{object_name}[#{attribute}]", record.send(record_id), object.send(attribute) == record.send(record_id), @field_options.merge({:id => element_id}))
|
95
97
|
|
96
98
|
content_tag(:label, :class => ['radio', ('inline' if @field_options[:inline])].compact.join(' ')) do
|
97
99
|
radiobutton + content_tag(:span, record.send(record_name))
|
@@ -118,95 +120,37 @@ module BootstrapForms
|
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@args = args
|
126
|
-
|
127
|
-
@field_options[:class] = 'btn btn-primary'
|
128
|
-
|
129
|
-
content_tag(:div, :class => 'form-actions') do
|
130
|
-
if @field_options[:include_cancel] == false
|
131
|
-
super(name, *(args << @field_options))
|
132
|
-
else
|
133
|
-
super(name, *(args << @field_options)) + ' ' + link_to(I18n.t('bootstrap_forms.buttons.cancel'), (@field_options[:back] || :back), :class => 'btn cancel')
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
private
|
140
|
-
def control_group_div(&block)
|
141
|
-
@field_options[:error] = error_string
|
142
|
-
|
143
|
-
klasses = ['control-group']
|
144
|
-
klasses << 'error' if @field_options[:error]
|
145
|
-
klasses << 'success' if @field_options[:success]
|
146
|
-
klasses << 'warning' if @field_options[:warning]
|
147
|
-
klass = klasses.join(' ')
|
148
|
-
|
149
|
-
content_tag(:div, :class => klass, &block)
|
150
|
-
end
|
151
|
-
|
152
|
-
def error_string
|
153
|
-
errors = object.errors[@name]
|
154
|
-
if errors.present?
|
155
|
-
errors.map { |e|
|
156
|
-
"#{@options[:label] || human_attribute_name} #{e}"
|
157
|
-
}.join(", ")
|
158
|
-
end
|
159
|
-
end
|
123
|
+
def button(name = nil, *args)
|
124
|
+
@name = name
|
125
|
+
@field_options = args.extract_options!
|
126
|
+
@args = args
|
160
127
|
|
161
|
-
|
162
|
-
|
128
|
+
@field_options[:class] = 'btn btn-primary'
|
129
|
+
super(name, *(args << @field_options))
|
163
130
|
end
|
164
131
|
|
165
|
-
def
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
klass = 'input-append' if @field_options[:append]
|
170
|
-
content_tag(:div, :class => klass, &block)
|
171
|
-
else
|
172
|
-
yield if block_given?
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
132
|
+
def submit(name = nil, *args)
|
133
|
+
@name = name
|
134
|
+
@field_options = args.extract_options!
|
135
|
+
@args = args
|
176
136
|
|
177
|
-
|
178
|
-
|
137
|
+
@field_options[:class] = 'btn btn-primary'
|
138
|
+
super(name, *(args << @field_options))
|
179
139
|
end
|
180
140
|
|
181
|
-
def
|
182
|
-
|
183
|
-
|
141
|
+
def cancel(*args)
|
142
|
+
@field_options = args.extract_options!
|
143
|
+
link_to(I18n.t('bootstrap_forms.buttons.cancel'), (@field_options[:back] || :back), :class => 'btn cancel')
|
184
144
|
end
|
185
145
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
when 'help_block'
|
191
|
-
element = :p
|
192
|
-
klass = 'help-block'
|
193
|
-
when 'append', 'prepend'
|
194
|
-
element = :span
|
195
|
-
klass = 'add-on'
|
146
|
+
def actions(&block)
|
147
|
+
content_tag(:div, :class => 'form-actions') do
|
148
|
+
if block_given?
|
149
|
+
yield
|
196
150
|
else
|
197
|
-
|
198
|
-
klass = 'help-inline'
|
151
|
+
[submit, cancel].join(' ').html_safe
|
199
152
|
end
|
200
|
-
content_tag(element, value, :class => klass)
|
201
153
|
end
|
202
154
|
end
|
203
|
-
|
204
|
-
def extras(&block)
|
205
|
-
[prepend, (yield if block_given?), append, help_inline, error, success, warning, help_block].join('').html_safe
|
206
|
-
end
|
207
|
-
|
208
|
-
def objectify_options(options)
|
209
|
-
super.except(:label, :help_inline, :error, :success, :warning, :help_block, :prepend, :append)
|
210
|
-
end
|
211
155
|
end
|
212
156
|
end
|
@@ -1,19 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module ActionView
|
1
|
+
module BootstrapForms
|
4
2
|
module Helpers
|
5
|
-
module FormHelper
|
3
|
+
module FormHelper
|
6
4
|
def bootstrap_form_for(record, options = {}, &block)
|
7
5
|
options[:builder] = BootstrapForms::FormBuilder
|
8
6
|
form_for(record, options) do |f|
|
9
7
|
f.error_messages.html_safe + capture(f, &block).html_safe
|
10
8
|
end
|
11
9
|
end
|
10
|
+
|
11
|
+
def bootstrap_fields_for(record, options = {}, &block)
|
12
|
+
options[:builder] = BootstrapForms::FormBuilder
|
13
|
+
fields_for(record, nil, options, &block)
|
14
|
+
end
|
12
15
|
end
|
13
16
|
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# don't wrap in those special divs
|
17
|
-
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance_tag|
|
18
|
-
html_tag
|
19
17
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module BootstrapForms
|
2
|
+
module Helpers
|
3
|
+
module FormTagHelper
|
4
|
+
include BootstrapForms::Helpers::Wrappers
|
5
|
+
|
6
|
+
def bootstrap_form_tag(url_for_options = {}, options = {}, &block)
|
7
|
+
form_tag(url_for_options, options, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
%w(button_tag check_box_tag email_field_tag field_set_tag file_field_tag image_submit_tag label_tag number_field_tag password_field_tag phone_field_tag radio_button_tag range_field_tag search_field_tag select_tag telephone_field_tag text_area_tag text_field_tag url_field_tag utf8_enforcer_tag).each do |method_name|
|
11
|
+
# prefix each method with bootstrap_*
|
12
|
+
define_method("bootstrap_#{method_name}") do |name, *args|
|
13
|
+
value = args.shift
|
14
|
+
@name = name
|
15
|
+
@field_options = args.extract_options!
|
16
|
+
@args = args
|
17
|
+
|
18
|
+
control_group_div do
|
19
|
+
label_field + input_div do
|
20
|
+
extras { send(method_name.to_sym, name, value, *(@args << @field_options)) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def uneditable_input_tag(name, *args)
|
27
|
+
@name = name
|
28
|
+
@field_options = args.extract_options!
|
29
|
+
@args = args
|
30
|
+
|
31
|
+
control_group_div do
|
32
|
+
label_field + input_div do
|
33
|
+
extras do
|
34
|
+
content_tag(:span, :class => 'uneditable-input') do
|
35
|
+
@field_options[:value] || object.send(@name.to_sym)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def bootstrap_button_tag(name = nil, *args)
|
43
|
+
@name = name
|
44
|
+
@field_options = args.extract_options!
|
45
|
+
@args = args
|
46
|
+
|
47
|
+
@field_options[:class] = 'btn btn-primary'
|
48
|
+
button_tag(name, *(args << @field_options))
|
49
|
+
end
|
50
|
+
|
51
|
+
def bootstrap_submit_tag(name = nil, *args)
|
52
|
+
@name = name
|
53
|
+
@field_options = args.extract_options!
|
54
|
+
@args = args
|
55
|
+
|
56
|
+
@field_options[:class] = 'btn btn-primary'
|
57
|
+
submit_tag(name, *(args << @field_options))
|
58
|
+
end
|
59
|
+
|
60
|
+
def bootstrap_cancel_tag(*args)
|
61
|
+
@field_options = args.extract_options!
|
62
|
+
link_to(I18n.t('bootstrap_forms.buttons.cancel'), (@field_options[:back] || :back), :class => 'btn cancel')
|
63
|
+
end
|
64
|
+
|
65
|
+
def bootstrap_actions(&block)
|
66
|
+
content_tag(:div, :class => 'form-actions') do
|
67
|
+
if block_given?
|
68
|
+
yield
|
69
|
+
else
|
70
|
+
[bootstrap_submit_tag, bootstrap_cancel_tag].join(' ').html_safe
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module BootstrapForms
|
2
|
+
module Helpers
|
3
|
+
module Wrappers
|
4
|
+
private
|
5
|
+
def control_group_div(&block)
|
6
|
+
field_errors = error_string
|
7
|
+
if @field_options[:error]
|
8
|
+
(@field_options[:error] << ", " << field_errors) if field_errors
|
9
|
+
else
|
10
|
+
@field_options[:error] = field_errors
|
11
|
+
end
|
12
|
+
|
13
|
+
klasses = ['control-group']
|
14
|
+
klasses << 'error' if @field_options[:error]
|
15
|
+
klasses << 'success' if @field_options[:success]
|
16
|
+
klasses << 'warning' if @field_options[:warning]
|
17
|
+
klass = klasses.join(' ')
|
18
|
+
|
19
|
+
content_tag(:div, :class => klass, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def error_string
|
23
|
+
if respond_to?(:object)
|
24
|
+
errors = object.errors[@name]
|
25
|
+
if errors.present?
|
26
|
+
errors.map { |e|
|
27
|
+
"#{@options[:label] || human_attribute_name} #{e}"
|
28
|
+
}.join(", ")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def human_attribute_name
|
34
|
+
object.class.human_attribute_name(@name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def input_div(&block)
|
38
|
+
content_tag(:div, :class => 'controls') do
|
39
|
+
if @field_options[:append] || @field_options[:prepend]
|
40
|
+
klass = 'input-prepend' if @field_options[:prepend]
|
41
|
+
klass = 'input-append' if @field_options[:append]
|
42
|
+
content_tag(:div, :class => klass, &block)
|
43
|
+
else
|
44
|
+
yield if block_given?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def label_field(&block)
|
50
|
+
if respond_to?(:object)
|
51
|
+
label(@name, block_given? ? block : @field_options[:label], :class => ['control-label', required_class].compact.join(' '))
|
52
|
+
else
|
53
|
+
label_tag(@name, block_given? ? block : @field_options[:label], :class => ['control-label', required_class].compact.join(' '))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def required_class
|
58
|
+
return 'required' if @field_options[:required]
|
59
|
+
if respond_to?(:object)
|
60
|
+
return 'required' if object.class.validators_on(@name).any? { |v| v.kind_of? ActiveModel::Validations::PresenceValidator }
|
61
|
+
end
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
%w(help_inline error success warning help_block append prepend).each do |method_name|
|
66
|
+
define_method(method_name) do |*args|
|
67
|
+
return '' unless value = @field_options[method_name.to_sym]
|
68
|
+
case method_name
|
69
|
+
when 'help_block'
|
70
|
+
element = :p
|
71
|
+
klass = 'help-block'
|
72
|
+
when 'append', 'prepend'
|
73
|
+
element = :span
|
74
|
+
klass = 'add-on'
|
75
|
+
else
|
76
|
+
element = :span
|
77
|
+
klass = 'help-inline'
|
78
|
+
end
|
79
|
+
content_tag(element, value, :class => klass)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def extras(&block)
|
84
|
+
[prepend, (yield if block_given?), append, help_inline, error, success, warning, help_block].join('').html_safe
|
85
|
+
end
|
86
|
+
|
87
|
+
def objectify_options(options)
|
88
|
+
super.except(:label, :help_inline, :error, :success, :warning, :help_block, :prepend, :append)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|