twitter-bootstrap-for-rails 1.3.3
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +694 -0
- data/Rakefile +1 -0
- data/app/helpers/bootstrap_panel_helper.rb +62 -0
- data/app/helpers/breadcrumbs_helper.rb +10 -0
- data/app/helpers/dropdown_helper.rb +144 -0
- data/app/helpers/flash_block_helper.rb +48 -0
- data/app/helpers/form_group_helper.rb +21 -0
- data/app/helpers/glyphicon_helper.rb +38 -0
- data/app/helpers/modal_dialog_helper.rb +81 -0
- data/app/helpers/navbar_helper.rb +234 -0
- data/app/helpers/paginator_helper.rb +63 -0
- data/app/helpers/resource_table_helper.rb +165 -0
- data/app/helpers/title_helper.rb +24 -0
- data/app/views/twitter-bootstrap/_breadcrumbs.erb +13 -0
- data/lib/bs_form_builder.rb +95 -0
- data/lib/form_builder.rb +125 -0
- data/lib/helpers.rb +14 -0
- data/lib/twitter/bootstrap/for/rails.rb +50 -0
- data/lib/twitter/bootstrap/for/rails/breadcrumbs.rb +65 -0
- data/lib/twitter/bootstrap/for/rails/version.rb +10 -0
- data/twitter-bootstrap-for-rails.gemspec +23 -0
- data/vendor/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/vendor/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/vendor/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/vendor/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/vendor/assets/javascripts/bootstrap.js +2002 -0
- data/vendor/assets/javascripts/bootstrap.min.js +9 -0
- data/vendor/assets/javascripts/bs-confirmation-dialog.js.erb +24 -0
- data/vendor/assets/stylesheets/bootstrap.css.erb +7098 -0
- data/vendor/assets/stylesheets/bootstrap.min.css.erb +9 -0
- metadata +105 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
module PaginatorHelper
|
4
|
+
def paginator(current_page, total_pages, options={})
|
5
|
+
content = []
|
6
|
+
|
7
|
+
state = current_page == 1 ? :disabled : :normal
|
8
|
+
param_name = options.delete(:param) || :page
|
9
|
+
content << page_item('«', current_page-1, state, param_name)
|
10
|
+
|
11
|
+
total_pages.times do |i|
|
12
|
+
page_num = i + 1
|
13
|
+
state = page_num == current_page ? :active : :normal
|
14
|
+
content << page_item(page_num, page_num, state, param_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
state = current_page == total_pages ? :disabled : :normal
|
18
|
+
content << page_item('»', current_page+1, state, param_name)
|
19
|
+
|
20
|
+
paginator_params = options.dup
|
21
|
+
paginator_params[:class] = parse_html_classes_to_arr paginator_params[:class]
|
22
|
+
paginator_params[:class] << 'pagination'
|
23
|
+
|
24
|
+
size = paginator_params.delete :size
|
25
|
+
|
26
|
+
case size
|
27
|
+
when :large
|
28
|
+
paginator_params[:class] << 'pagination-lg'
|
29
|
+
when :small
|
30
|
+
paginator_params[:class] << 'pagination-sm'
|
31
|
+
end
|
32
|
+
|
33
|
+
content_tag :ul, content.join("\n").html_safe, paginator_params
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def page_item(text, page_num, state, param_name)
|
38
|
+
options = {}
|
39
|
+
|
40
|
+
case state
|
41
|
+
when :disabled, :active
|
42
|
+
content = content_tag :span, text
|
43
|
+
options[:class] = state
|
44
|
+
else
|
45
|
+
content = link_to text, "#{request.path}?#{param_name}=#{page_num}#{additional_uri_params}"
|
46
|
+
end
|
47
|
+
|
48
|
+
content_tag :li, content, options
|
49
|
+
end
|
50
|
+
|
51
|
+
def additional_uri_params
|
52
|
+
additionalParams = ''
|
53
|
+
exceptedKeys = ['page', 'action', 'controller']
|
54
|
+
|
55
|
+
params.each do |key, value|
|
56
|
+
unless exceptedKeys.include? key.downcase
|
57
|
+
additionalParams << "&#{key}=#{value}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
additionalParams
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
module ResourceTableHelper
|
4
|
+
def resource_table(model, collection, methods, options={})
|
5
|
+
classes = parse_html_classes_to_arr options[:class]
|
6
|
+
classes << 'table'
|
7
|
+
|
8
|
+
table_options = options.dup
|
9
|
+
table_options[:class] = classes
|
10
|
+
|
11
|
+
can_create = table_options.delete(:can_create)
|
12
|
+
can_show = table_options.delete(:can_show)
|
13
|
+
can_remove = table_options.delete(:can_remove)
|
14
|
+
can_edit = table_options.delete(:can_edit)
|
15
|
+
remove_confirmation = table_options.delete :remove_confirmation
|
16
|
+
|
17
|
+
can_remove = true if can_remove.nil?
|
18
|
+
can_show = true if can_show.nil?
|
19
|
+
can_create = true if can_create.nil?
|
20
|
+
can_edit = true if can_edit.nil?
|
21
|
+
|
22
|
+
content = []
|
23
|
+
content << render_thead(model, methods, can_create , can_show, can_remove, can_edit)
|
24
|
+
content << render_tbody(collection, methods, can_create, can_show, can_remove, can_edit, remove_confirmation)
|
25
|
+
|
26
|
+
content_tag :table, content.join("\n").html_safe, table_options
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def render_thead(model, methods, can_create, can_show, can_remove, can_edit)
|
31
|
+
content_tag :thead, render_header_row(model, methods, can_create, can_show, can_remove, can_edit)
|
32
|
+
end
|
33
|
+
|
34
|
+
def render_header_row(model, methods, can_create, can_show, can_remove, can_edit)
|
35
|
+
content_tag :tr, render_header_columns(model, methods, can_create, can_show, can_remove, can_edit)
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_header_columns(model, methods, can_create, can_show, can_remove, can_edit)
|
39
|
+
content = []
|
40
|
+
add_button = render_add_button(model) if can_create
|
41
|
+
|
42
|
+
if can_create || can_show || can_edit
|
43
|
+
content << content_tag(:th, add_button)
|
44
|
+
end
|
45
|
+
|
46
|
+
methods.each do |method|
|
47
|
+
m = method
|
48
|
+
|
49
|
+
if method.is_a? Array
|
50
|
+
m = method[0]
|
51
|
+
end
|
52
|
+
|
53
|
+
content << content_tag(:th, model.human_attribute_name(m))
|
54
|
+
end
|
55
|
+
|
56
|
+
if can_remove
|
57
|
+
content << content_tag(:th)
|
58
|
+
end
|
59
|
+
|
60
|
+
content.join("\n").html_safe
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_add_button(model)
|
64
|
+
link_to glyph(:plus), [:new, model.model_name.singular], class: 'btn btn-default btn-xs'
|
65
|
+
end
|
66
|
+
|
67
|
+
def render_tbody(collection, methods, can_create, can_show, can_remove, can_edit, remove_confirmation)
|
68
|
+
content_tag :tbody, render_rows(collection, methods, can_create, can_show, can_remove, can_edit, remove_confirmation)
|
69
|
+
end
|
70
|
+
|
71
|
+
def render_rows(collection, methods, can_create, can_show, can_remove, can_edit, remove_confirmation)
|
72
|
+
if collection.empty?
|
73
|
+
# render_empty_row methods, can_create, can_show, can_remove, can_edit
|
74
|
+
else
|
75
|
+
content = []
|
76
|
+
|
77
|
+
collection.each do |item|
|
78
|
+
content << content_tag(:tr, render_columns(item, methods, can_create, can_show, can_edit, can_remove, remove_confirmation))
|
79
|
+
end
|
80
|
+
|
81
|
+
content.join("\n").html_safe
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def render_empty_row(methods, can_create, can_show, can_remove, can_edit)
|
86
|
+
col_count = methods.count
|
87
|
+
|
88
|
+
if can_create || can_show || can_edit
|
89
|
+
col_count += 1
|
90
|
+
end
|
91
|
+
|
92
|
+
if can_remove
|
93
|
+
col_count += 1
|
94
|
+
end
|
95
|
+
|
96
|
+
# TODO: I18n
|
97
|
+
col = content_tag :td, 'Items not found', colspan: col_count, class: 'text-center'
|
98
|
+
content_tag :tr, col
|
99
|
+
end
|
100
|
+
|
101
|
+
def render_columns(item, methods, can_create, can_show, can_edit, can_remove, remove_confirmation)
|
102
|
+
content = []
|
103
|
+
|
104
|
+
if can_create || can_show || can_edit
|
105
|
+
content << content_tag(:td, render_show_and_edit(item, can_show, can_edit))
|
106
|
+
end
|
107
|
+
|
108
|
+
methods.each do |method|
|
109
|
+
if method.is_a? Array
|
110
|
+
value = item
|
111
|
+
|
112
|
+
method.each do |submethod|
|
113
|
+
value = value.try submethod
|
114
|
+
end
|
115
|
+
else
|
116
|
+
value = item.try method
|
117
|
+
end
|
118
|
+
|
119
|
+
content << content_tag(:td, value)
|
120
|
+
end
|
121
|
+
|
122
|
+
if can_remove
|
123
|
+
content << content_tag(:td, render_remove_button(item, remove_confirmation))
|
124
|
+
end
|
125
|
+
|
126
|
+
content.join("\n").html_safe
|
127
|
+
end
|
128
|
+
|
129
|
+
def render_remove_button(item, remove_confirmation)
|
130
|
+
if remove_confirmation.blank?
|
131
|
+
confirm_text = I18n.t 'bootstrap.resource_table.remove_confirmation', default: 'Remove this item?'
|
132
|
+
else
|
133
|
+
if remove_confirmation.is_a? Proc
|
134
|
+
confirm_text = remove_confirmation.yield item
|
135
|
+
else
|
136
|
+
confirm_text = evaluate_confirm_text remove_confirmation.to_s, item
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
link_to glyph(:remove), item, class: 'btn btn-danger btn-xs', method: :delete, data: {confirm: confirm_text}
|
141
|
+
end
|
142
|
+
|
143
|
+
def evaluate_confirm_text(text, item)
|
144
|
+
eval text
|
145
|
+
rescue
|
146
|
+
return text
|
147
|
+
end
|
148
|
+
|
149
|
+
def render_show_and_edit(item, can_show, can_edit)
|
150
|
+
content = []
|
151
|
+
|
152
|
+
if can_show
|
153
|
+
content << link_to(glyph(:eye_open), item, class: 'btn btn-default btn-xs')
|
154
|
+
end
|
155
|
+
|
156
|
+
if can_edit
|
157
|
+
content << link_to(glyph(:edit), [:edit, item], class: 'btn btn-default btn-xs')
|
158
|
+
end
|
159
|
+
|
160
|
+
content_tag :div, content.join("\n").html_safe, class: 'btn-group'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# resource_table Organization, @organizations, [:name, [:workers, :count]], remove_confirmation: 'Are you shure?'
|
165
|
+
# resource_table Organization, @organizations, [:name, [:workers, :count]], remove_confirmation: {|item| "Delete #{item.to_s}?"}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module TitleHelper
|
2
|
+
def page_title(text=nil)
|
3
|
+
title = text.to_s
|
4
|
+
|
5
|
+
if text.nil?
|
6
|
+
if action_name == 'update'
|
7
|
+
title = t("page_titles.#{controller_name}.edit")
|
8
|
+
end
|
9
|
+
|
10
|
+
if action_name == 'create'
|
11
|
+
title = t("page_titles.#{controller_name}.new")
|
12
|
+
end
|
13
|
+
|
14
|
+
title = t("page_titles.#{controller_name}.#{action_name}", default: title)
|
15
|
+
end
|
16
|
+
|
17
|
+
if text.is_a? Symbol
|
18
|
+
title = t("page_titles.#{controller_name}.#{text}")
|
19
|
+
end
|
20
|
+
|
21
|
+
content_for :title, "<div class=\"page-header\"><h1>#{title}</h1></div>".html_safe
|
22
|
+
content_tag :title, "#{"#{title} |" unless title.blank?} #{t :application_title}"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<% if @breadcrumbs.present? %>
|
2
|
+
<%= content_tag :ol, options do %>
|
3
|
+
<% @breadcrumbs[0..-2].each do |crumb| %>
|
4
|
+
<li>
|
5
|
+
<%= link_to crumb[:name], crumb[:url], crumb[:options] %>
|
6
|
+
</li>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<li class="active">
|
10
|
+
<%= @breadcrumbs.last[:name] %>
|
11
|
+
</li>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
class BsFormBuilder
|
2
|
+
require 'helpers'
|
3
|
+
|
4
|
+
class_attribute :form_control_fields
|
5
|
+
self.form_control_fields = ActionView::Helpers::FormBuilder.form_control_fields
|
6
|
+
|
7
|
+
def initialize(template, object_name, method)
|
8
|
+
@template = template
|
9
|
+
@method = method
|
10
|
+
@object_name = object_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def label(text = nil, options = {}, &block)
|
14
|
+
if text.is_a? Hash
|
15
|
+
label_text = nil
|
16
|
+
label_options = text.dup
|
17
|
+
else
|
18
|
+
label_text = text
|
19
|
+
label_options = options.dup
|
20
|
+
end
|
21
|
+
|
22
|
+
label_classes = parse_html_classes_to_arr label_options[:class]
|
23
|
+
add_html_class label_classes, 'control-label'
|
24
|
+
label_options[:class] = label_classes
|
25
|
+
|
26
|
+
@template.label @method, label_text, label_options, &block
|
27
|
+
end
|
28
|
+
|
29
|
+
def validation_error
|
30
|
+
@template.validation_error @method
|
31
|
+
end
|
32
|
+
|
33
|
+
form_control_fields.each do |selector|
|
34
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
35
|
+
def #{selector}(options = {}) # def text_field(options = {})
|
36
|
+
field_classes = parse_html_classes_to_arr options[:class] # field_classes = parse_html_classes_to_arr options[:class]
|
37
|
+
add_html_class field_classes, 'form-control' # add_html_class field_classes, 'form-control'
|
38
|
+
field_options = options.dup # field_options = options.dup
|
39
|
+
field_options[:class] = field_classes # field_options[:class] = field_classes
|
40
|
+
#
|
41
|
+
@template.send( # @template.send(
|
42
|
+
#{selector.inspect}, # "text_field",
|
43
|
+
@method, # @method,
|
44
|
+
field_options) # field_options)
|
45
|
+
end # end
|
46
|
+
RUBY_EVAL
|
47
|
+
end
|
48
|
+
|
49
|
+
def submit(value=nil, options={})
|
50
|
+
if value.is_a?(Hash)
|
51
|
+
value, submit_options = nil, value.dup
|
52
|
+
else
|
53
|
+
submit_options = options.dup
|
54
|
+
end
|
55
|
+
|
56
|
+
classes = parse_html_classes_to_arr submit_options[:class]
|
57
|
+
classes << 'btn'
|
58
|
+
classes << 'btn-primary'
|
59
|
+
submit_options[:class] = classes
|
60
|
+
|
61
|
+
@template.submit(value, submit_options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def static
|
65
|
+
@template.bs_static_control @method
|
66
|
+
end
|
67
|
+
|
68
|
+
def collection_select(collection, value_method, text_method, options = {}, html_options = {})
|
69
|
+
select_html_options = html_options.dup
|
70
|
+
classes = parse_html_classes_to_arr select_html_options[:class]
|
71
|
+
classes << 'form-control'
|
72
|
+
select_html_options[:class] = classes
|
73
|
+
|
74
|
+
@template.collection_select(@method, collection, value_method, text_method, options, select_html_options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def check_box(text=nil, options = {}, checked_value = '1', unchecked_value = '0')
|
78
|
+
if text.is_a? Hash
|
79
|
+
text, options = nil, text
|
80
|
+
end
|
81
|
+
|
82
|
+
label_text = text || @template.object.class.human_attribute_name(@method)
|
83
|
+
|
84
|
+
control = @template.check_box @method, options, checked_value, unchecked_value
|
85
|
+
content = @template.label @method do
|
86
|
+
"#{label_text}\n#{control}".html_safe
|
87
|
+
end
|
88
|
+
|
89
|
+
check_box_options = options.dup
|
90
|
+
check_box_options[:class] = parse_html_classes_to_arr check_box_options[:class]
|
91
|
+
check_box_options[:class] << 'checkbox'
|
92
|
+
|
93
|
+
@template.content_tag :div, content, check_box_options
|
94
|
+
end
|
95
|
+
end
|
data/lib/form_builder.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
class ActionView::Helpers::FormBuilder
|
2
|
+
include ActionView::Context
|
3
|
+
include ActionView::Helpers::TagHelper
|
4
|
+
require 'helpers'
|
5
|
+
|
6
|
+
class_attribute :form_control_fields
|
7
|
+
self.form_control_fields = ActionView::Helpers::FormBuilder.field_helpers - [:label, :check_box, :radio_button, :fields_for, :hidden_field, :file_field]
|
8
|
+
|
9
|
+
require 'bs_form_builder'
|
10
|
+
|
11
|
+
def form_group(method=nil, options={}, &block)
|
12
|
+
raise ArgumentError, 'Missing block' unless block_given?
|
13
|
+
|
14
|
+
method, options = nil, method if method.is_a? Hash
|
15
|
+
|
16
|
+
form_group_options = options.dup
|
17
|
+
classes = parse_html_classes_to_arr options[:class]
|
18
|
+
add_html_class classes, 'form-group'
|
19
|
+
form_group_options[:class] = classes
|
20
|
+
bs_form_helper = BsFormBuilder.new self, @object_name, method
|
21
|
+
content = @template.capture(bs_form_helper, &block)
|
22
|
+
|
23
|
+
if method
|
24
|
+
if @object.errors[method].any?
|
25
|
+
add_html_class classes, 'has-error'
|
26
|
+
end
|
27
|
+
|
28
|
+
if render_validation_error? options
|
29
|
+
content << validation_error(method)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
content_tag :div, content, form_group_options
|
34
|
+
end
|
35
|
+
|
36
|
+
def validation_error(method)
|
37
|
+
if @object.errors[method].any?
|
38
|
+
errors = @object.errors[method].join(' ')
|
39
|
+
content_tag(:span, errors, class: [:'helper-block', :'text-danger'])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
form_control_fields.each do |selector|
|
44
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
45
|
+
def #{selector}(method, options = {}) # def text_field(method, options = {})
|
46
|
+
field_options = options.dup # field_options = options.dup
|
47
|
+
set_placeholder_and_title method, field_options # set_placeholder_and_title field_options method, field_options
|
48
|
+
if @object.class.validators_on(method).map(&:class).include?(ActiveRecord::Validations::PresenceValidator)
|
49
|
+
if field_options[:required] == nil
|
50
|
+
field_options[:required] = true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
#
|
54
|
+
@template.send( # @template.send(
|
55
|
+
#{selector.inspect}, # "text_field",
|
56
|
+
@object_name, # @object_name,
|
57
|
+
method, # method,
|
58
|
+
objectify_options(field_options)) # objectify_options(options))
|
59
|
+
end # end
|
60
|
+
RUBY_EVAL
|
61
|
+
end
|
62
|
+
|
63
|
+
def label(method, text = nil, options = {}, &block)
|
64
|
+
if text.is_a? Hash
|
65
|
+
label_text = nil
|
66
|
+
label_options = text.dup
|
67
|
+
else
|
68
|
+
label_text = text
|
69
|
+
label_options = options.dup
|
70
|
+
end
|
71
|
+
|
72
|
+
label_classes = parse_html_classes_to_arr label_options[:class]
|
73
|
+
|
74
|
+
if @object.class.validators_on(method).map(&:class).include?(ActiveRecord::Validations::PresenceValidator)
|
75
|
+
add_html_class label_classes, 'required-label'
|
76
|
+
end
|
77
|
+
|
78
|
+
label_options[:class] = label_classes
|
79
|
+
|
80
|
+
@template.label @object_name, method, label_text, label_options, &block
|
81
|
+
end
|
82
|
+
|
83
|
+
def bs_static_control(method)
|
84
|
+
content_tag :p, @object.send(method), class: 'form-control-static'
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
def set_placeholder_and_title(method, options)
|
89
|
+
scope = [:activerecord, :placeholders, object.class.model_name.i18n_key]
|
90
|
+
|
91
|
+
if options[:placeholder]
|
92
|
+
if options[:placeholder].is_a? Symbol
|
93
|
+
placeholder = I18n.t(options[:placeholder], scope: scope, default: '')
|
94
|
+
else
|
95
|
+
placeholder = options[:placeholder].to_s
|
96
|
+
end
|
97
|
+
else
|
98
|
+
placeholder = I18n.t(method, scope: scope, default: '')
|
99
|
+
end
|
100
|
+
|
101
|
+
if placeholder.blank?
|
102
|
+
options.delete :placeholder
|
103
|
+
else
|
104
|
+
options[:placeholder] = placeholder
|
105
|
+
options[:title] = placeholder
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def render_validation_error?(options)
|
110
|
+
form_html_options = @options[:html] || {}
|
111
|
+
form_classes = parse_html_classes_to_arr form_html_options[:class]
|
112
|
+
|
113
|
+
if Twitter::Bootstrap::For::Rails.render_validation_error == false
|
114
|
+
false
|
115
|
+
elsif form_classes.include?('form-inline') || form_classes.include?('form-horizontal')
|
116
|
+
false
|
117
|
+
elsif @options[:render_validation_error] == false
|
118
|
+
false
|
119
|
+
elsif options[:render_validation_error] == false
|
120
|
+
false
|
121
|
+
else
|
122
|
+
true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|