twitter-bootstrap-for-rails 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
module BootstrapPanelHelper
|
4
|
+
def panel(options={}, &block)
|
5
|
+
unless block_given?
|
6
|
+
raise 'Missing block'
|
7
|
+
end
|
8
|
+
|
9
|
+
panel_options = options.dup
|
10
|
+
panel_options[:class] = parse_html_classes_to_arr panel_options[:class]
|
11
|
+
panel_options[:class] << 'panel'
|
12
|
+
|
13
|
+
header = panel_options.delete :header
|
14
|
+
title = panel_options.delete :title
|
15
|
+
footer = panel_options.delete :footer
|
16
|
+
context = panel_options.delete :context
|
17
|
+
|
18
|
+
unless %w(primary info success warning danger).include? context.to_s
|
19
|
+
context = :default
|
20
|
+
end
|
21
|
+
|
22
|
+
panel_options[:class] << "panel-#{context}"
|
23
|
+
|
24
|
+
content = []
|
25
|
+
content << panel_header(header || title)
|
26
|
+
content << panel_body(&block)
|
27
|
+
content << panel_footer(footer)
|
28
|
+
|
29
|
+
content_tag :div, content.join("\n").html_safe, panel_options
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def panel_body(&block)
|
34
|
+
content = capture &block
|
35
|
+
|
36
|
+
content_tag :div, content, class: 'panel-body'
|
37
|
+
end
|
38
|
+
|
39
|
+
def panel_header(header)
|
40
|
+
return unless header
|
41
|
+
|
42
|
+
if header.is_a? Hash
|
43
|
+
level = header[:level]
|
44
|
+
|
45
|
+
unless (1..6).include? level
|
46
|
+
level = 1
|
47
|
+
end
|
48
|
+
|
49
|
+
content = content_tag "h#{level}", header[:content], class: 'panel-title'
|
50
|
+
else
|
51
|
+
content = header
|
52
|
+
end
|
53
|
+
|
54
|
+
content_tag :div, content, class: 'panel-heading'
|
55
|
+
end
|
56
|
+
|
57
|
+
def panel_footer(content)
|
58
|
+
if content
|
59
|
+
content_tag :div, content, class: 'panel-footer'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
module BreadcrumbsHelper
|
4
|
+
def render_breadcrumbs(options={})
|
5
|
+
br_options = options.dup
|
6
|
+
br_options[:class] = parse_html_classes_to_arr br_options[:class]
|
7
|
+
br_options[:class] << 'breadcrumb'
|
8
|
+
render :partial => 'twitter-bootstrap/breadcrumbs', :layout => false, locals: {options: br_options}
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module DropdownHelper
|
2
|
+
require 'helpers'
|
3
|
+
|
4
|
+
def dropdown(text, options={}, &block)
|
5
|
+
container_options = options.dup
|
6
|
+
button_options = container_options.delete(:button) || {}
|
7
|
+
menu_options = container_options.delete(:menu) || {}
|
8
|
+
|
9
|
+
drop_direction = container_options.delete :drop_direction
|
10
|
+
container_classes = parse_html_classes_to_arr container_options[:class]
|
11
|
+
container_classes << 'btn-group'
|
12
|
+
|
13
|
+
if drop_direction == :up
|
14
|
+
container_classes << 'dropup'
|
15
|
+
end
|
16
|
+
|
17
|
+
container_options[:class] = container_classes
|
18
|
+
|
19
|
+
content_tag :div, render_dropdown(text, button_options, menu_options, &block), container_options
|
20
|
+
end
|
21
|
+
|
22
|
+
class Dropdown
|
23
|
+
include ActionView::Helpers::TagHelper
|
24
|
+
|
25
|
+
def item(text, link_or_options=nil, options={})
|
26
|
+
if link_or_options.is_a? Hash
|
27
|
+
link_or_options, options = nil, link_or_options
|
28
|
+
end
|
29
|
+
|
30
|
+
link_or_options ||= '#'
|
31
|
+
|
32
|
+
content = content_tag :a, text, href: link_or_options
|
33
|
+
content_tag :li, content, options
|
34
|
+
end
|
35
|
+
|
36
|
+
def divider(options={})
|
37
|
+
classes = parse_html_classes_to_arr options[:class]
|
38
|
+
classes << 'divider'
|
39
|
+
divider_options = options.dup
|
40
|
+
divider_options[:class] = classes
|
41
|
+
content_tag :li, '', divider_options
|
42
|
+
end
|
43
|
+
|
44
|
+
def header(text, options={})
|
45
|
+
header_options = options.dup
|
46
|
+
classes = parse_html_classes_to_arr header_options[:class]
|
47
|
+
classes << 'dropdown-header'
|
48
|
+
header_options[:class] = classes
|
49
|
+
|
50
|
+
content_tag :li, text, header_options
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def render_dropdown(button_text, button_options, menu_options, &block)
|
56
|
+
content = []
|
57
|
+
content << render_button(button_text, button_options)
|
58
|
+
content << render_menu(menu_options, &block)
|
59
|
+
content.join("\n").html_safe
|
60
|
+
end
|
61
|
+
|
62
|
+
def btn_regex
|
63
|
+
/btn-(?>default|primary|warning|success|info|danger|link)/
|
64
|
+
end
|
65
|
+
|
66
|
+
def render_button(button_text, options={})
|
67
|
+
split = options[:split]
|
68
|
+
|
69
|
+
button_classes = parse_html_classes_to_arr options[:class]
|
70
|
+
|
71
|
+
unless button_classes.join =~ btn_regex
|
72
|
+
button_classes << 'btn-default'
|
73
|
+
options[:class] = button_classes
|
74
|
+
end
|
75
|
+
|
76
|
+
if split
|
77
|
+
render_split_button button_text, options
|
78
|
+
else
|
79
|
+
render_single_button button_text, options
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_split_options(button_options)
|
84
|
+
split_options =
|
85
|
+
case button_options[:split]
|
86
|
+
when Hash then button_options[:split]
|
87
|
+
else {}
|
88
|
+
end
|
89
|
+
|
90
|
+
classes = parse_html_classes_to_arr split_options[:class]
|
91
|
+
|
92
|
+
unless classes.join =~ btn_regex
|
93
|
+
classes << btn_regex.match(parse_html_classes_to_arr(button_options[:class]).join)
|
94
|
+
end
|
95
|
+
|
96
|
+
classes << 'btn'
|
97
|
+
classes << 'dropdown-toggle'
|
98
|
+
split_options[:class] = classes
|
99
|
+
split_options[:type] = 'button'
|
100
|
+
split_options[:data] = { toggle: 'dropdown' }
|
101
|
+
|
102
|
+
split_options
|
103
|
+
end
|
104
|
+
|
105
|
+
def render_single_button(button_text, options)
|
106
|
+
content = []
|
107
|
+
content << button_text
|
108
|
+
content << caret
|
109
|
+
|
110
|
+
button_classes = parse_html_classes_to_arr options[:class]
|
111
|
+
button_classes << 'btn dropdown-toggle'
|
112
|
+
options[:class] = button_classes
|
113
|
+
options[:type] = 'button'
|
114
|
+
options[:data] = { toggle: 'dropdown' }
|
115
|
+
|
116
|
+
content_tag :button, content.join("\n").html_safe, options
|
117
|
+
end
|
118
|
+
|
119
|
+
def render_split_button(button_text, options)
|
120
|
+
content = []
|
121
|
+
split_options = get_split_options(options)
|
122
|
+
options.delete :split
|
123
|
+
|
124
|
+
classes = parse_html_classes_to_arr options[:class]
|
125
|
+
classes << 'btn'
|
126
|
+
options[:class] = classes
|
127
|
+
options[:type] = 'button'
|
128
|
+
|
129
|
+
content << content_tag(:button, button_text, options)
|
130
|
+
content << content_tag(:button, caret, split_options)
|
131
|
+
content.join("\n").html_safe
|
132
|
+
end
|
133
|
+
|
134
|
+
def caret
|
135
|
+
content_tag :span, '', class: 'caret'
|
136
|
+
end
|
137
|
+
|
138
|
+
def render_menu(options, &block)
|
139
|
+
content = capture Dropdown.new, &block
|
140
|
+
options[:class] = 'dropdown-menu'
|
141
|
+
options[:role] = 'menu'
|
142
|
+
content_tag :ul, content, options
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
module FlashBlockHelper
|
4
|
+
def flash_block(options={})
|
5
|
+
content = []
|
6
|
+
|
7
|
+
flash.each do |type, message|
|
8
|
+
content << bs_alert(type, message)
|
9
|
+
end
|
10
|
+
|
11
|
+
content_tag :div, content.join("\n").html_safe, options
|
12
|
+
end
|
13
|
+
|
14
|
+
def bs_alert(type, message, options={})
|
15
|
+
alert_options = options.dup
|
16
|
+
alert_options[:class] = parse_html_classes_to_arr alert_options[:class]
|
17
|
+
alert_options[:class] << 'alert'
|
18
|
+
alert_options[:class] << 'alert-dismissable'
|
19
|
+
alert_options[:class] << alert_class(type)
|
20
|
+
|
21
|
+
content = []
|
22
|
+
content << content_tag(:button, '×'.html_safe, class: 'close', type: 'button', data: {dismiss: :alert}, aria: {hidden: 'true'})
|
23
|
+
content << message
|
24
|
+
|
25
|
+
content_tag :div, content.join("\n").html_safe, alert_options
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
#Render rules
|
30
|
+
#- `:success` render as `.alert-success`;
|
31
|
+
#- `:info` render as `.alert-info`;
|
32
|
+
#- `:warning` render as `.alert-warning`;
|
33
|
+
#- `:danger` render as `.alert-danger`;
|
34
|
+
#- `:notice` render as `.alert-success`;
|
35
|
+
#- `:alert` render as `.alert-danger`;
|
36
|
+
#- another keys render as `alert-info`.
|
37
|
+
def alert_class(type)
|
38
|
+
act_type =
|
39
|
+
case type
|
40
|
+
when :success, :notice then :success
|
41
|
+
when :danger, :alert then :danger
|
42
|
+
when :warning, :info then type
|
43
|
+
else :info
|
44
|
+
end
|
45
|
+
|
46
|
+
"alert-#{act_type}"
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module FormGroupHelper
|
2
|
+
# Return a bootstrap form group markup
|
3
|
+
def form_group(options = {}, &block)
|
4
|
+
form_group_options = options.dup
|
5
|
+
classes = split_html_class options[:class]
|
6
|
+
classes << :'form-group'
|
7
|
+
form_group_options[:class] = classes
|
8
|
+
content = capture &block
|
9
|
+
content_tag :div, content, form_group_options
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def split_html_class(classes)
|
14
|
+
case classes
|
15
|
+
when NilClass then []
|
16
|
+
when String then classes.split
|
17
|
+
when Array then classes
|
18
|
+
when Symbol then [classes]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GlyphiconHelper
|
2
|
+
require 'helpers'
|
3
|
+
|
4
|
+
# Return the Twitter Bootstrap glyphicon html markup
|
5
|
+
# Parameter name is the name of icon
|
6
|
+
# Parameter options is the hash of additional options generating span
|
7
|
+
#
|
8
|
+
#
|
9
|
+
# invoke
|
10
|
+
# glyph :search
|
11
|
+
#
|
12
|
+
# returns
|
13
|
+
# <span class="glyphicon glyphicon-search"></span>
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# invoke
|
17
|
+
# glyph :search, class: 'pull-right'
|
18
|
+
#
|
19
|
+
# returns
|
20
|
+
# <span class="pull-right glyphicon glyphicon-search"></span>
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# invoke
|
24
|
+
# glyph :search, class: 'pull-right', data: { action: 'search' }
|
25
|
+
#
|
26
|
+
# returns
|
27
|
+
# <span class="pull-right glyphicon glyphicon-search" data-action="search"></span>
|
28
|
+
def glyph(name, options={})
|
29
|
+
glyph_options = options.dup
|
30
|
+
glyph_classes = parse_html_classes_to_arr glyph_options[:class]
|
31
|
+
glyph_classes << 'glyphicon'
|
32
|
+
glyph_classes << "glyphicon-#{name.to_s.gsub('_', '-')}"
|
33
|
+
glyph_options[:class] = glyph_classes
|
34
|
+
|
35
|
+
|
36
|
+
content_tag :span, '', glyph_options
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
module ModalDialogHelper
|
4
|
+
def modal_dialog(options={})
|
5
|
+
modal_dialog_options = options.dup
|
6
|
+
modal_dialog_options[:class] = parse_html_classes_to_arr modal_dialog_options[:class]
|
7
|
+
modal_dialog_options[:class] << 'modal'
|
8
|
+
modal_dialog_options[:class] << 'fade'
|
9
|
+
|
10
|
+
modal_header = modal_dialog_options.delete :header
|
11
|
+
modal_body = modal_dialog_options.delete :body
|
12
|
+
modal_footer = modal_dialog_options.delete :footer
|
13
|
+
|
14
|
+
modal_dialog_builder = ModalDialog.new self, modal_header, modal_body, modal_footer
|
15
|
+
|
16
|
+
content = modal_dialog_builder.render
|
17
|
+
|
18
|
+
content_tag :div, content, modal_dialog_options
|
19
|
+
end
|
20
|
+
|
21
|
+
def dismiss_button(text, options={})
|
22
|
+
#<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
23
|
+
button_options = options.dup
|
24
|
+
button_options[:class] = parse_html_classes_to_arr button_options[:class]
|
25
|
+
button_options[:class] << 'btn'
|
26
|
+
button_options[:data] ||= {}
|
27
|
+
button_options[:data][:dismiss] = 'modal'
|
28
|
+
|
29
|
+
unless button_options[:class].join =~ /btn-(?>default|primary|warning|success|info|danger|link)/
|
30
|
+
button_options[:class] << 'btn-default'
|
31
|
+
end
|
32
|
+
|
33
|
+
content_tag :button, text, button_options
|
34
|
+
end
|
35
|
+
|
36
|
+
class ModalDialog
|
37
|
+
attr_accessor :parent, :header, :body, :footer
|
38
|
+
delegate :content_tag, to: :parent
|
39
|
+
|
40
|
+
def initialize(parent, header, body, footer)
|
41
|
+
@parent = parent
|
42
|
+
@header = header
|
43
|
+
@body = body
|
44
|
+
@footer = footer
|
45
|
+
end
|
46
|
+
|
47
|
+
def render
|
48
|
+
content_tag :div, modal_content_block, class: 'modal-dialog'
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def modal_content_block
|
53
|
+
content = []
|
54
|
+
content << modal_header_block
|
55
|
+
content << modal_body_block
|
56
|
+
content << modal_footer_block
|
57
|
+
|
58
|
+
content_tag :div, content.join("\n").html_safe, class: 'modal-content'
|
59
|
+
end
|
60
|
+
|
61
|
+
def modal_header_block
|
62
|
+
if @header
|
63
|
+
content_tag :div, close_button + @header, class: 'modal-header'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def close_button
|
68
|
+
content_tag :button, '×'.html_safe, type: 'button', class: 'close', data: {dismiss: 'modal'}, aria: {hidden: 'true'}
|
69
|
+
end
|
70
|
+
|
71
|
+
def modal_body_block
|
72
|
+
content_tag :div, @body, class: 'modal-body'
|
73
|
+
end
|
74
|
+
|
75
|
+
def modal_footer_block
|
76
|
+
if @footer
|
77
|
+
content_tag :div, @footer, class: 'modal-footer'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module NavbarHelper
|
2
|
+
require 'helpers'
|
3
|
+
|
4
|
+
def navbar(options={}, &block)
|
5
|
+
navbar_options = options.dup
|
6
|
+
navbar_options[:class] = parse_html_classes_to_arr navbar_options[:class]
|
7
|
+
navbar_options[:class] << 'navbar'
|
8
|
+
navbar_options[:class] << 'navbar-default'
|
9
|
+
navbar_options[:role] = :navigation
|
10
|
+
|
11
|
+
fixed = navbar_options.delete(:fixed).to_s
|
12
|
+
|
13
|
+
if fixed == 'top' || fixed == 'bottom'
|
14
|
+
navbar_options[:class] << "navbar-fixed-#{fixed}"
|
15
|
+
end
|
16
|
+
|
17
|
+
static = navbar_options.delete(:static).to_s
|
18
|
+
|
19
|
+
if static == 'top'
|
20
|
+
navbar_options[:class] << 'navbar-static-top'
|
21
|
+
end
|
22
|
+
|
23
|
+
inverse = navbar_options.delete :inverse
|
24
|
+
|
25
|
+
if inverse == true
|
26
|
+
navbar_options[:class] << 'navbar-inverse'
|
27
|
+
end
|
28
|
+
|
29
|
+
brand = navbar_options.delete :brand
|
30
|
+
|
31
|
+
navbar_id = SecureRandom.hex
|
32
|
+
|
33
|
+
content = []
|
34
|
+
content << render_navbar_header(brand, navbar_id)
|
35
|
+
content << render_navbar_body(navbar_id, &block)
|
36
|
+
|
37
|
+
content_tag :nav, content.join("\n").html_safe, navbar_options
|
38
|
+
end
|
39
|
+
|
40
|
+
def uri_state(uri)
|
41
|
+
root_url = request.host_with_port + '/'
|
42
|
+
request_uri = request.path[1..-1]
|
43
|
+
|
44
|
+
uri.gsub(root_url)
|
45
|
+
|
46
|
+
if uri.start_with? '/'
|
47
|
+
uri = uri[1..-1]
|
48
|
+
end
|
49
|
+
|
50
|
+
if uri == request_uri
|
51
|
+
return :active
|
52
|
+
end
|
53
|
+
|
54
|
+
uri_parts = uri.split '/'
|
55
|
+
request_uri_parts = request_uri.split '/'
|
56
|
+
|
57
|
+
uri_parts.each_with_index do |uri_part, index|
|
58
|
+
if uri_part != request_uri_parts[index]
|
59
|
+
return :inactive
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
:chosen
|
64
|
+
end
|
65
|
+
|
66
|
+
class Navbar
|
67
|
+
attr_accessor :parent
|
68
|
+
|
69
|
+
def initialize(parent)
|
70
|
+
self.parent = parent
|
71
|
+
end
|
72
|
+
|
73
|
+
delegate :capture, :content_tag, :to => :parent
|
74
|
+
|
75
|
+
def group(options={}, &block)
|
76
|
+
navbar_group_builder = NavbarGroup.new self.parent
|
77
|
+
content = capture navbar_group_builder, &block
|
78
|
+
|
79
|
+
menu_group_options = options.dup
|
80
|
+
menu_group_options[:class] = parse_html_classes_to_arr menu_group_options[:class]
|
81
|
+
menu_group_options[:class] << 'nav'
|
82
|
+
menu_group_options[:class] << 'navbar-nav'
|
83
|
+
pull = menu_group_options.delete(:pull).to_s
|
84
|
+
|
85
|
+
if pull == 'left' || pull == 'right'
|
86
|
+
menu_group_options[:class] << "navbar-#{pull}"
|
87
|
+
end
|
88
|
+
|
89
|
+
content_tag :ul, content, menu_group_options
|
90
|
+
end
|
91
|
+
|
92
|
+
def button(text, options={})
|
93
|
+
button_options = options.dup
|
94
|
+
button_options[:class] = parse_html_classes_to_arr button_options[:class]
|
95
|
+
button_options[:class] << 'btn'
|
96
|
+
button_options[:class] << 'navbar-btn'
|
97
|
+
|
98
|
+
unless button_options[:class].join =~ /btn-(?>default|primary|warning|success|info|danger|link)/
|
99
|
+
button_options[:class] << 'btn-default'
|
100
|
+
end
|
101
|
+
|
102
|
+
content_tag :button, text, button_options
|
103
|
+
end
|
104
|
+
|
105
|
+
def text(text, options={})
|
106
|
+
text_options = options.dup
|
107
|
+
text_options[:class] = parse_html_classes_to_arr text_options[:class]
|
108
|
+
text_options[:class] << 'navbar-text'
|
109
|
+
|
110
|
+
pull = text_options.delete(:pull).to_s
|
111
|
+
|
112
|
+
if pull == 'left' || pull == 'right'
|
113
|
+
text_options[:class] << "navbar-#{pull}"
|
114
|
+
end
|
115
|
+
|
116
|
+
content_tag :p, text, text_options
|
117
|
+
end
|
118
|
+
|
119
|
+
def link(text, uri, options={})
|
120
|
+
link_options = options.dup
|
121
|
+
link_options[:class] = parse_html_classes_to_arr link_options[:class]
|
122
|
+
link_options[:class] << 'navbar-link'
|
123
|
+
link_options[:href] = uri
|
124
|
+
|
125
|
+
content_tag :a, text, link_options
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class NavbarGroup
|
130
|
+
attr_accessor :parent
|
131
|
+
|
132
|
+
def initialize(parent)
|
133
|
+
self.parent = parent
|
134
|
+
end
|
135
|
+
|
136
|
+
delegate :capture, :content_tag, :request, :link_to, :uri_state, :to => :parent
|
137
|
+
|
138
|
+
def item(text, uri, options={})
|
139
|
+
menu_item_options = options.dup
|
140
|
+
menu_item_options[:class] = parse_html_classes_to_arr menu_item_options[:class]
|
141
|
+
|
142
|
+
state = uri_state uri
|
143
|
+
|
144
|
+
if state == :active || state == :chosen
|
145
|
+
menu_item_options[:class] << 'active'
|
146
|
+
end
|
147
|
+
|
148
|
+
content = link_to text, uri
|
149
|
+
content_tag :li, content, menu_item_options
|
150
|
+
end
|
151
|
+
|
152
|
+
def dropdown(text, options={}, &block)
|
153
|
+
dropdown_builder = Dropdown.new self.parent
|
154
|
+
content = []
|
155
|
+
content << link_to("#{text} #{caret}".html_safe, '#', class: 'dropdown-toggle', data: {toggle: 'dropdown'})
|
156
|
+
items = capture dropdown_builder, &block
|
157
|
+
content << content_tag(:ul, items, class: 'dropdown-menu')
|
158
|
+
|
159
|
+
dropdown_options = options.dup
|
160
|
+
dropdown_options[:class] = parse_html_classes_to_arr dropdown_options[:class]
|
161
|
+
dropdown_options[:class] << 'dropdown'
|
162
|
+
|
163
|
+
if dropdown_builder.chosen
|
164
|
+
dropdown_options[:class] << 'active'
|
165
|
+
end
|
166
|
+
|
167
|
+
content_tag :li, content.join("\n").html_safe, dropdown_options
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
def caret
|
172
|
+
content_tag :span, '', class: 'caret'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class Dropdown
|
177
|
+
attr_accessor :parent, :chosen
|
178
|
+
|
179
|
+
def initialize(parent)
|
180
|
+
self.parent = parent
|
181
|
+
@chosen = false
|
182
|
+
end
|
183
|
+
|
184
|
+
delegate :capture, :content_tag, :request, :link_to, :uri_state, :to => :parent
|
185
|
+
|
186
|
+
def item(text, uri, options={})
|
187
|
+
menu_item_options = options.dup
|
188
|
+
menu_item_options[:class] = parse_html_classes_to_arr menu_item_options[:class]
|
189
|
+
|
190
|
+
state = uri_state uri
|
191
|
+
|
192
|
+
if state == :active || state == :chosen
|
193
|
+
menu_item_options[:class] << 'active'
|
194
|
+
@chosen = true
|
195
|
+
end
|
196
|
+
|
197
|
+
content = link_to text, uri
|
198
|
+
content_tag :li, content, menu_item_options
|
199
|
+
end
|
200
|
+
|
201
|
+
def divider
|
202
|
+
content_tag :li, '', class: 'divider'
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
def render_navbar_header(brand, navbar_id)
|
208
|
+
content = []
|
209
|
+
content << navbar_collapse_button(navbar_id)
|
210
|
+
|
211
|
+
unless brand.blank?
|
212
|
+
content << link_to(brand, root_path, class: 'navbar-brand')
|
213
|
+
end
|
214
|
+
|
215
|
+
content_tag :div, content.join("\n").html_safe, class: 'navbar-header'
|
216
|
+
end
|
217
|
+
|
218
|
+
def navbar_collapse_button(navbar_id)
|
219
|
+
content = []
|
220
|
+
|
221
|
+
3.times do
|
222
|
+
content << content_tag(:span, '', class: 'icon-bar')
|
223
|
+
end
|
224
|
+
|
225
|
+
content_tag :button, content.join("\n").html_safe, type: 'button', class: 'navbar-toggle',
|
226
|
+
data: {toggle: 'collapse', target: "##{navbar_id}"}
|
227
|
+
end
|
228
|
+
|
229
|
+
def render_navbar_body(navbar_id, &block)
|
230
|
+
navbar_builder = Navbar.new self
|
231
|
+
content = capture navbar_builder, &block
|
232
|
+
content_tag :div, content, class: 'collapse navbar-collapse', id: navbar_id
|
233
|
+
end
|
234
|
+
end
|