bootstrap_ui_helper 0.3.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +48 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/bootstrap_ui_helper.js +113 -0
- data/app/assets/stylesheets/bootstrap_ui_helper.css +12 -0
- data/app/helpers/alert_box_helper.rb +50 -0
- data/app/helpers/badge_helper.rb +12 -0
- data/app/helpers/bootstrap_form_helper.rb +191 -0
- data/app/helpers/bootstrap_form_options_helper.rb +141 -0
- data/app/helpers/breadcrumb_helper.rb +23 -0
- data/app/helpers/button_helper.rb +91 -0
- data/app/helpers/button_to_helper.rb +17 -0
- data/app/helpers/dropdown_helper.rb +137 -0
- data/app/helpers/format_helper.rb +12 -0
- data/app/helpers/icon_helper.rb +112 -0
- data/app/helpers/label_helper.rb +33 -0
- data/app/helpers/link_helper.rb +53 -0
- data/app/helpers/modal_helper.rb +65 -0
- data/app/helpers/nav_helper.rb +56 -0
- data/app/helpers/navbar_helper.rb +68 -0
- data/app/helpers/panel_helper.rb +78 -0
- data/app/helpers/panel_row_helper.rb +12 -0
- data/app/helpers/progress_bar_helper.rb +72 -0
- data/app/helpers/valid_icons.rb +160 -0
- data/bootstrap_ui_helper.gemspec +23 -0
- data/codeclimate.yml +58 -0
- data/lib/bootstrap_ui_helper.rb +6 -0
- data/lib/bootstrap_ui_helper/version.rb +3 -0
- metadata +103 -0
@@ -0,0 +1,141 @@
|
|
1
|
+
module BootstrapFormOptionsHelper
|
2
|
+
|
3
|
+
class ActionView::Helpers::FormBuilder
|
4
|
+
include FormatHelper
|
5
|
+
include BootstrapFormHelper
|
6
|
+
|
7
|
+
|
8
|
+
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
9
|
+
label_class, field_wrapper = horizontal_layout? ? ['col-sm-3 control-label', true] : []
|
10
|
+
|
11
|
+
required = 'required' if html_options.delete(:required)
|
12
|
+
label_sr_only = 'sr-only' if html_options[:label].is_a?(FalseClass)
|
13
|
+
html_options[:class] = squeeze_n_strip("form-control #{html_options[:class]}")
|
14
|
+
label_class = squeeze_n_strip("#{label_class} #{required} #{label_sr_only}")
|
15
|
+
help_text = (html_options[:help] ? "<span class='help-block text-left'>#{html_options[:help]}</span>" : '').html_safe
|
16
|
+
|
17
|
+
select_proc = proc do
|
18
|
+
@template.select(@object_name,
|
19
|
+
method,
|
20
|
+
choices,
|
21
|
+
objectify_options(options),
|
22
|
+
@default_options.merge(html_options),
|
23
|
+
&block) + help_text
|
24
|
+
end
|
25
|
+
|
26
|
+
label_proc = proc { label(method, html_options[:label], class: label_class) }
|
27
|
+
|
28
|
+
render_field(field_wrapper, label_proc, select_proc)
|
29
|
+
end
|
30
|
+
|
31
|
+
def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
32
|
+
check_boxes_proc = proc do
|
33
|
+
@template.collection_check_boxes(@object_name, method, collection, value_method, text_method,
|
34
|
+
objectify_options(options), @default_options.merge(html_options),
|
35
|
+
&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
render_collection(options[:label], &check_boxes_proc)
|
39
|
+
end
|
40
|
+
|
41
|
+
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
42
|
+
radion_buttons_prc = proc do
|
43
|
+
@template.collection_radio_buttons(@object_name, method, collection, value_method, text_method,
|
44
|
+
objectify_options(options), @default_options.merge(html_options),
|
45
|
+
&block)
|
46
|
+
end
|
47
|
+
|
48
|
+
render_collection(options[:label], &radion_buttons_prc)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def render_label(label)
|
54
|
+
label_class = 'col-sm-3 control-label' if horizontal_layout?
|
55
|
+
|
56
|
+
label.present? ? "<label class='#{label_class}'>#{label}</label> " : ''
|
57
|
+
end
|
58
|
+
|
59
|
+
def render_input(&input_block)
|
60
|
+
horizontal_layout? ? (content_tag :div, class: 'col-sm-9', &input_block) : yield
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_collection(label, &input_block)
|
64
|
+
content_tag :div, class: 'form-group' do
|
65
|
+
(render_label(label) + render_input(&input_block)).html_safe
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def horizontal_layout?
|
70
|
+
BootstrapFormHelper.layout == :horizontal
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class ActionView::Helpers::Tags::CollectionCheckBoxes
|
75
|
+
attr_accessor :output_buffer
|
76
|
+
|
77
|
+
def render(&block)
|
78
|
+
rendered_collection = render_collection do |item, value, text, default_html_options|
|
79
|
+
default_html_options[:multiple] = true
|
80
|
+
builder = instantiate_builder(CheckBoxBuilder, item, value, text, default_html_options)
|
81
|
+
|
82
|
+
if block_given?
|
83
|
+
@template_object.capture(builder, &block)
|
84
|
+
else
|
85
|
+
render_check_box(builder, @options.fetch(:inline, false))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if @options.fetch(:include_hidden, true)
|
90
|
+
rendered_collection + hidden_field
|
91
|
+
else
|
92
|
+
rendered_collection
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def render_check_box(builder, inline=false)
|
99
|
+
label_class, input_wrapper = 'checkbox-inline', true if inline
|
100
|
+
|
101
|
+
input_proc = proc do
|
102
|
+
content_tag :label, class: label_class do
|
103
|
+
builder.check_box + ' ' + builder.text
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
input_wrapper ? input_proc.call : (content_tag :div, class: 'checkbox', &input_proc)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class ActionView::Helpers::Tags::CollectionRadioButtons
|
112
|
+
attr_accessor :output_buffer
|
113
|
+
|
114
|
+
def render(&block)
|
115
|
+
render_collection do |item, value, text, default_html_options|
|
116
|
+
builder = instantiate_builder(RadioButtonBuilder, item, value, text, default_html_options)
|
117
|
+
|
118
|
+
if block_given?
|
119
|
+
@template_object.capture(builder, &block)
|
120
|
+
else
|
121
|
+
render_radio_button(builder, @options.fetch(:inline, false))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def render_radio_button(builder, inline=false)
|
129
|
+
label_class, input_wrapper = 'radio-inline', true if inline
|
130
|
+
|
131
|
+
input_proc = proc do
|
132
|
+
content_tag :label, class: label_class do
|
133
|
+
builder.radio_button + ' ' + builder.text
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
input_wrapper ? input_proc.call : (content_tag :div, class: 'radio', &input_proc)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module BreadcrumbHelper
|
2
|
+
include FormatHelper
|
3
|
+
|
4
|
+
def breadcrumb(links=[], options={})
|
5
|
+
return if links.blank?
|
6
|
+
|
7
|
+
prepend_class(options, 'breadcrumb')
|
8
|
+
|
9
|
+
content_tag :ol, options do
|
10
|
+
links.map.with_index do |link, index|
|
11
|
+
render_li(link, (index == links.length - 1))
|
12
|
+
end.join('').html_safe
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_li(link, last_li)
|
17
|
+
active = {class: 'active'} if last_li
|
18
|
+
|
19
|
+
content_tag :li, active do
|
20
|
+
last_li ? link[:text] : (link_to link.delete(:text), link.delete(:link), link)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module ButtonHelper
|
2
|
+
include ActionView::Helpers
|
3
|
+
include FormatHelper
|
4
|
+
|
5
|
+
def button(content_or_options=nil, options={}, &block)
|
6
|
+
content_or_options.is_a?(Hash) ? options = content_or_options : content = content_or_options
|
7
|
+
|
8
|
+
layout = 'btn-block' if options.delete(:layout).try(:to_sym) == :block
|
9
|
+
size = get_btn_size(options.delete(:size))
|
10
|
+
type = get_btn_type(options.delete(:type))
|
11
|
+
prepend_class(options, 'btn', type, size, layout)
|
12
|
+
|
13
|
+
content_tag :button, options do
|
14
|
+
content.presence || capture(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def button_group(options={}, &block)
|
19
|
+
size = get_btn_group_size(options.delete(:size))
|
20
|
+
layout = if options.delete(:layout).try(:to_sym) == :vertical
|
21
|
+
'btn-group-vertical'
|
22
|
+
else
|
23
|
+
'btn-group'
|
24
|
+
end
|
25
|
+
|
26
|
+
prepend_class(options, layout, size)
|
27
|
+
options[:role] = squeeze_n_strip("group #{options[:role]}")
|
28
|
+
options[:data] = (options[:data] || {}).merge({bui: 'btn_group', size: size})
|
29
|
+
|
30
|
+
content_tag :div, options, &block
|
31
|
+
end
|
32
|
+
|
33
|
+
def button_toolbar(options={}, &block)
|
34
|
+
prepend_class(options, 'btn-toolbar')
|
35
|
+
prepend_role(options, 'toolbar')
|
36
|
+
|
37
|
+
content_tag :div, options, &block
|
38
|
+
end
|
39
|
+
|
40
|
+
def navbar_button(content_or_options=nil, options={}, &block)
|
41
|
+
content_or_options.is_a?(Hash) ? options = content_or_options : content = content_or_options
|
42
|
+
|
43
|
+
prepend_class(options, 'navbar-btn')
|
44
|
+
button content, options, &block
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def get_btn_size(size)
|
50
|
+
case size.try(:to_sym)
|
51
|
+
when :xsmall
|
52
|
+
'btn-xs'
|
53
|
+
when :small
|
54
|
+
'btn-sm'
|
55
|
+
when :large
|
56
|
+
'btn-lg'
|
57
|
+
else
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_btn_type(type)
|
62
|
+
case type.try(:to_sym)
|
63
|
+
when :primary
|
64
|
+
'btn-primary'
|
65
|
+
when :info
|
66
|
+
'btn-info'
|
67
|
+
when :success
|
68
|
+
'btn-success'
|
69
|
+
when :warning
|
70
|
+
'btn-warning'
|
71
|
+
when :danger
|
72
|
+
'btn-danger'
|
73
|
+
when :link
|
74
|
+
'btn-link'
|
75
|
+
else
|
76
|
+
'btn-default'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_btn_group_size(size)
|
81
|
+
case size.try(:to_sym)
|
82
|
+
when :xsmall
|
83
|
+
'btn-group-xs'
|
84
|
+
when :small
|
85
|
+
'btn-group-sm'
|
86
|
+
when :large
|
87
|
+
'btn-group-lg'
|
88
|
+
else
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ButtonToHelper
|
2
|
+
include FormatHelper
|
3
|
+
|
4
|
+
def button_to(name = nil, options = nil, html_options = nil, &block)
|
5
|
+
html_options, options = options, name if block_given?
|
6
|
+
options ||= {}
|
7
|
+
html_options ||= {}
|
8
|
+
|
9
|
+
layout = 'btn-block' if html_options.delete(:layout).try(:to_sym) == :block
|
10
|
+
size = get_btn_size(html_options.delete(:size))
|
11
|
+
style = get_btn_type(html_options.delete(:style))
|
12
|
+
|
13
|
+
prepend_class(html_options, 'btn', style, layout, size)
|
14
|
+
|
15
|
+
super(name, options, html_options, &block)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module DropdownHelper
|
2
|
+
|
3
|
+
# TODO: support split button dropdowns
|
4
|
+
class DropdownListItem
|
5
|
+
include FormatHelper
|
6
|
+
include ActionView::Helpers
|
7
|
+
|
8
|
+
attr_accessor :options
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def construct
|
15
|
+
content_tag :li, parse_type(options), options
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_type(options={})
|
19
|
+
case options[:type].try(:to_sym)
|
20
|
+
when :link
|
21
|
+
return link_to(options[:text], options[:link], role: :menuitem,
|
22
|
+
tabindex: -1)
|
23
|
+
when :header
|
24
|
+
prepend_class(options, 'dropdown-header')
|
25
|
+
return options[:text]
|
26
|
+
when :divider
|
27
|
+
prepend_class(options, 'divider')
|
28
|
+
options[:role] = 'separator'
|
29
|
+
else
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class DropdownCreator
|
35
|
+
include FormatHelper
|
36
|
+
include ActionView::Helpers
|
37
|
+
|
38
|
+
attr_accessor :content
|
39
|
+
attr_accessor :list
|
40
|
+
attr_accessor :options
|
41
|
+
attr_accessor :output_buffer
|
42
|
+
|
43
|
+
def initialize(content, list, options)
|
44
|
+
@content = content
|
45
|
+
@list = list
|
46
|
+
@options = options
|
47
|
+
end
|
48
|
+
|
49
|
+
def build
|
50
|
+
navbar, btn_id, klass, align, direction, size, type = process_dropdown_options(options)
|
51
|
+
|
52
|
+
btn_options = button_options(content, size, type, btn_id, navbar)
|
53
|
+
list_options = list_options(btn_id, align)
|
54
|
+
|
55
|
+
tag = navbar ? :li : :div
|
56
|
+
prepend_class(options, 'btn-group',
|
57
|
+
(direction == :up ? 'dropup' : 'dropdown'), klass)
|
58
|
+
|
59
|
+
content_tag tag, options do
|
60
|
+
(dropdown_button(btn_options) +
|
61
|
+
dropdown_list(list, list_options)).html_safe
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def process_dropdown_options(options)
|
67
|
+
navbar = options.delete(:category).try(:to_sym) == :navbar
|
68
|
+
btn_id = options.delete(:id) || "dropdown-#{rand(0...999)}"
|
69
|
+
klass = options.delete(:class)
|
70
|
+
active = 'active' if options.delete(:active)
|
71
|
+
align = options.delete(:align).try(:to_sym)
|
72
|
+
direction = options.delete(:direction).try(:to_sym)
|
73
|
+
size = get_btn_size(options.delete(:size))
|
74
|
+
type = get_btn_type(options.delete(:type))
|
75
|
+
|
76
|
+
[navbar, btn_id, "#{klass} #{active}", align, direction, size,
|
77
|
+
"btn #{type}"]
|
78
|
+
end
|
79
|
+
|
80
|
+
def button_options(content, size, type, id, navbar)
|
81
|
+
klass = navbar ? 'dropdown-toggle' : "dropdown-toggle #{size} #{type}"
|
82
|
+
|
83
|
+
{
|
84
|
+
content: content,
|
85
|
+
class: klass,
|
86
|
+
id: id,
|
87
|
+
data: {toggle: 'dropdown'},
|
88
|
+
aria: {haspopup: true, expended: false},
|
89
|
+
navbar: navbar
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def list_options(btn_id, align)
|
94
|
+
{
|
95
|
+
class: align == :right ? 'dropdown-menu-right' : 'dropdown-menu-left',
|
96
|
+
role: 'menu',
|
97
|
+
aria: {labelledby: btn_id}
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def dropdown_button(options={})
|
102
|
+
content = options.delete(:content)
|
103
|
+
navbar = options.delete(:navbar)
|
104
|
+
|
105
|
+
if navbar
|
106
|
+
link_to '#', options do
|
107
|
+
(content + " <span class='caret'></span>").html_safe
|
108
|
+
end
|
109
|
+
else
|
110
|
+
button_tag options do
|
111
|
+
(content + " <span class='caret'></span>").html_safe
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def dropdown_list(list_items, options={})
|
117
|
+
prepend_class(options, 'dropdown-menu')
|
118
|
+
|
119
|
+
content_tag :ul, options do
|
120
|
+
list_items.map do |item|
|
121
|
+
DropdownListItem.new(item).construct
|
122
|
+
end.join('').html_safe
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def dropdown(content=nil, list=[], options={})
|
129
|
+
return if content.blank? || list.empty?
|
130
|
+
|
131
|
+
DropdownCreator.new(content, list, options).build
|
132
|
+
end
|
133
|
+
|
134
|
+
def navbar_dropdown(content=nil, list=[], options={})
|
135
|
+
dropdown(content, list, options.merge({category: :navbar}))
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module FormatHelper
|
2
|
+
|
3
|
+
def squeeze_n_strip(string='')
|
4
|
+
string.squeeze(' ').strip
|
5
|
+
end
|
6
|
+
|
7
|
+
%w(class role).each do |attr|
|
8
|
+
define_method "prepend_#{attr}" do |options={}, *attrs|
|
9
|
+
options[attr.to_sym] = squeeze_n_strip("#{attrs.join(' ')} #{options[attr.to_sym]}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module IconHelper
|
2
|
+
|
3
|
+
class IconCreator
|
4
|
+
include ValidIcons
|
5
|
+
include FormatHelper
|
6
|
+
include ActionView::Helpers
|
7
|
+
|
8
|
+
attr_accessor :type
|
9
|
+
attr_accessor :options
|
10
|
+
|
11
|
+
def initialize(type, options)
|
12
|
+
@type = type
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
icon_options = {
|
18
|
+
type: type,
|
19
|
+
size: options.delete(:size).presence || :normal,
|
20
|
+
fw: options.delete(:fixed_with).presence,
|
21
|
+
li: options.delete(:list_icon).presence,
|
22
|
+
inverse: options.delete(:inverse).presence,
|
23
|
+
border: options.delete(:border).presence,
|
24
|
+
pull: options.delete(:pull).presence,
|
25
|
+
animate: options.delete(:animate).presence,
|
26
|
+
orientation: options.delete(:orientation).presence
|
27
|
+
|
28
|
+
# TODO add fa-stack support
|
29
|
+
# stack = options.delete(:stack).presence
|
30
|
+
}
|
31
|
+
|
32
|
+
prepend_class(options, 'fa', build_fa_class(icon_options))
|
33
|
+
|
34
|
+
content_tag :i, nil, options
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def build_fa_class(options)
|
39
|
+
type = "fa-#{options[:type]}"
|
40
|
+
raise 'Invalid Icon Type!' if ValidIcons::VALID_ICONS.exclude?(type)
|
41
|
+
|
42
|
+
size = get_icon_size(options.delete(:size))
|
43
|
+
fw = options[:fw].presence ? 'fa-fw' : nil
|
44
|
+
li = options[:li].presence ? 'fa-li' : nil
|
45
|
+
inverse = options[:inverse].presence ? 'fa-inverse' : nil
|
46
|
+
border = options[:border].presence ? 'fa-border' : nil
|
47
|
+
pull = get_icon_position(options[:pull])
|
48
|
+
animate = get_icon_animation(options[:animate])
|
49
|
+
orientation = get_icon_orientation(options[:orientation])
|
50
|
+
|
51
|
+
"#{type} #{size} #{fw} #{li} #{inverse} #{border} #{pull} #{animate} #{orientation}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_icon_size(size)
|
55
|
+
case size.try(:to_sym)
|
56
|
+
when :lg
|
57
|
+
'fa-lg'
|
58
|
+
when :'2x'
|
59
|
+
'fa-2x'
|
60
|
+
when :'3x'
|
61
|
+
'fa-3x'
|
62
|
+
when :'4x'
|
63
|
+
'fa-4x'
|
64
|
+
when :'5x'
|
65
|
+
'fa-5x'
|
66
|
+
else
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_icon_position(position)
|
71
|
+
case position.try(:to_sym)
|
72
|
+
when :right
|
73
|
+
'fa-pull-right'
|
74
|
+
when :left
|
75
|
+
'fa-pull-left'
|
76
|
+
else
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_icon_animation(animation)
|
81
|
+
case animation.try(:to_sym)
|
82
|
+
when :spin
|
83
|
+
'fa-spin'
|
84
|
+
when :pulse
|
85
|
+
'fa-pulse'
|
86
|
+
else
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_icon_orientation(orientation)
|
91
|
+
case orientation.try(:to_sym)
|
92
|
+
when :'90'
|
93
|
+
'fa-rotate-90'
|
94
|
+
when :'180'
|
95
|
+
'fa-rotate-180'
|
96
|
+
when :'270'
|
97
|
+
'fa-rotate-270'
|
98
|
+
when :horizontal
|
99
|
+
'fa-flip-horizontal'
|
100
|
+
when :vertical
|
101
|
+
'fa-flip-vertical'
|
102
|
+
else
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def icon(type=nil, options={})
|
108
|
+
raise 'Please provide an icon type!' if type.blank?
|
109
|
+
|
110
|
+
IconCreator.new(type, options).build
|
111
|
+
end
|
112
|
+
end
|