menu_helper 0.1.0 → 0.2.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/CHANGELOG.rdoc +4 -0
- data/Rakefile +1 -1
- data/lib/menu_helper/html_element.rb +39 -41
- data/lib/menu_helper/menu.rb +124 -126
- data/lib/menu_helper/menu_bar.rb +188 -190
- data/lib/menu_helper.rb +103 -105
- data/test/helpers/menu_helper_test.rb +1 -1
- data/test/unit/html_element_test.rb +7 -7
- data/test/unit/menu_bar_test.rb +22 -22
- data/test/unit/menu_test.rb +53 -53
- metadata +14 -14
data/CHANGELOG.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -1,46 +1,44 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
:
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
1
|
+
module MenuHelper
|
2
|
+
# Represents an HTML element
|
3
|
+
#
|
4
|
+
# == Modifying HTML options
|
5
|
+
#
|
6
|
+
# HTML options can normally be specified when creating the element.
|
7
|
+
# However, if they need to be modified after the element has been created,
|
8
|
+
# you can access the properties like so:
|
9
|
+
#
|
10
|
+
# m = Menu.new
|
11
|
+
# m[:style] = 'display: none;'
|
12
|
+
#
|
13
|
+
# or for a menu bar:
|
14
|
+
#
|
15
|
+
# b = MenuBar.new
|
16
|
+
# b[:style] = 'display: none;'
|
17
|
+
class HtmlElement
|
18
|
+
include ActionView::Helpers::TagHelper
|
19
|
+
|
20
|
+
delegate :[],
|
21
|
+
:[]=,
|
22
|
+
:to => '@html_options'
|
23
|
+
|
24
|
+
def initialize(html_options = {}) #:nodoc:
|
25
|
+
@html_options = html_options.symbolize_keys
|
26
|
+
end
|
27
|
+
|
28
|
+
# Generates the html representing this element
|
29
|
+
def html
|
30
|
+
content_tag(tag_name, content, @html_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
# The name of the element tag to use (e.g. td, th, tr, etc.)
|
35
|
+
def tag_name
|
36
|
+
''
|
27
37
|
end
|
28
38
|
|
29
|
-
#
|
30
|
-
def
|
31
|
-
|
39
|
+
# The content that will be displayed inside of the tag
|
40
|
+
def content
|
41
|
+
''
|
32
42
|
end
|
33
|
-
|
34
|
-
private
|
35
|
-
# The name of the element tag to use (e.g. td, th, tr, etc.)
|
36
|
-
def tag_name
|
37
|
-
''
|
38
|
-
end
|
39
|
-
|
40
|
-
# The content that will be displayed inside of the tag
|
41
|
-
def content
|
42
|
-
''
|
43
|
-
end
|
44
|
-
end
|
45
43
|
end
|
46
44
|
end
|
data/lib/menu_helper/menu.rb
CHANGED
@@ -1,148 +1,146 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module MenuHelper
|
2
|
+
# Represents a single menu within a menu bar
|
3
|
+
class Menu < HtmlElement
|
4
|
+
include ActionView::Helpers::UrlHelper
|
5
|
+
|
6
|
+
# The css class to apply when a menu is selected
|
7
|
+
cattr_accessor :selected_class
|
8
|
+
@@selected_class = 'menubar-selected'
|
9
|
+
|
10
|
+
# The css class for the last menu in the menu bar
|
11
|
+
cattr_accessor :last_class
|
12
|
+
@@last_class = 'menubar-last'
|
13
|
+
|
14
|
+
# The unique name assigned to this menu
|
15
|
+
attr_reader :name
|
16
|
+
|
17
|
+
# The url where this menu is linked to. This can either be a hash of
|
18
|
+
# url options or a string representing the actual url
|
19
|
+
attr_reader :url_options
|
20
|
+
|
21
|
+
# The menu bar in which this menu exists
|
22
|
+
attr_reader :parent_menu_bar
|
23
|
+
|
24
|
+
# Add shortcuts to the menu bar configuration
|
25
|
+
delegate :request_controller,
|
26
|
+
:parent_menu,
|
27
|
+
:auto_set_ids?,
|
28
|
+
:attach_active_submenus?,
|
29
|
+
:to => :parent_menu_bar
|
30
|
+
|
31
|
+
# Add ability to add menus *after* creation
|
32
|
+
delegate :menu,
|
33
|
+
:to => '@menu_bar'
|
34
|
+
|
35
|
+
def initialize(parent_menu_bar, name, content = nil, url_options = {}, html_options = {}) #:nodoc
|
36
|
+
# Allow the content parameter to be skipped
|
37
|
+
content, url_options, html_options = nil, content, url_options if content.is_a?(Hash)
|
6
38
|
|
7
|
-
#
|
8
|
-
|
9
|
-
|
39
|
+
# Remove non-html options that are specific to this element and shouldn't
|
40
|
+
# be rendered as an html attribute
|
41
|
+
@options = html_options.slice(:link)
|
42
|
+
html_options.except!(:link)
|
10
43
|
|
11
|
-
|
12
|
-
cattr_accessor :last_class
|
13
|
-
@@last_class = 'menubar-last'
|
44
|
+
super(html_options)
|
14
45
|
|
15
|
-
|
16
|
-
|
46
|
+
@parent_menu_bar = parent_menu_bar
|
47
|
+
@name = name.to_s
|
17
48
|
|
18
|
-
#
|
19
|
-
|
20
|
-
attr_reader :url_options
|
49
|
+
# Set context of the menu for url generation
|
50
|
+
@controller = request_controller
|
21
51
|
|
22
|
-
#
|
23
|
-
|
52
|
+
# Generate the text-based content of the menu
|
53
|
+
@content = content_tag(:span, content || @name.underscore.titleize)
|
24
54
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
:auto_set_ids?,
|
29
|
-
:attach_active_submenus?,
|
30
|
-
:to => :parent_menu_bar
|
55
|
+
# Set up url
|
56
|
+
url, @url_options = build_url(url_options)
|
57
|
+
@content = link_to(@content, url) if @options[:link] != false
|
31
58
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
59
|
+
# Set up default html options
|
60
|
+
id_prefix = parent_menu_bar[:id] || parent_menu && parent_menu[:id]
|
61
|
+
self[:id] ||= "#{id_prefix}-#{@name}" if auto_set_ids? && id_prefix
|
35
62
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
# Remove non-html options that are specific to this element and shouldn't
|
41
|
-
# be rendered as an html attribute
|
42
|
-
@options = html_options.slice(:link)
|
43
|
-
html_options.except!(:link)
|
44
|
-
|
45
|
-
super(html_options)
|
46
|
-
|
47
|
-
@parent_menu_bar = parent_menu_bar
|
48
|
-
@name = name.to_s
|
49
|
-
|
50
|
-
# Set context of the menu for url generation
|
51
|
-
@controller = request_controller
|
52
|
-
|
53
|
-
# Generate the text-based content of the menu
|
54
|
-
@content = content_tag(:span, content || @name.underscore.titleize)
|
55
|
-
|
56
|
-
# Set up url
|
57
|
-
url, @url_options = build_url(url_options)
|
58
|
-
@content = link_to(@content, url) if @options[:link] != false
|
59
|
-
|
60
|
-
# Set up default html options
|
61
|
-
id_prefix = parent_menu_bar[:id] || parent_menu && parent_menu[:id]
|
62
|
-
self[:id] ||= "#{id_prefix}-#{@name}" if auto_set_ids? && id_prefix
|
63
|
-
|
64
|
-
# Create the menu bar for sub-menus in case any are generated. Use the
|
65
|
-
# same configuration as the parent menu bar.
|
66
|
-
@menu_bar = MenuBar.new(request_controller, parent_menu_bar.options.merge(:parent_menu => self))
|
67
|
-
|
68
|
-
yield @menu_bar if block_given?
|
69
|
-
end
|
63
|
+
# Create the menu bar for sub-menus in case any are generated. Use the
|
64
|
+
# same configuration as the parent menu bar.
|
65
|
+
@menu_bar = MenuBar.new(request_controller, parent_menu_bar.options.merge(:parent_menu => self))
|
70
66
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
67
|
+
yield @menu_bar if block_given?
|
68
|
+
end
|
69
|
+
|
70
|
+
# Is this menu selected? A menu is considered selected if it or any of
|
71
|
+
# its sub-menus are selected
|
72
|
+
def selected?
|
73
|
+
current_page?(url_options) || @menu_bar.selected?
|
74
|
+
end
|
75
|
+
|
76
|
+
# Builds the actual html of the menu
|
77
|
+
def html(last = false)
|
78
|
+
html_options = @html_options.dup
|
79
|
+
html_options[:class] = "#{html_options[:class]} #{selected_class}".strip if selected?
|
80
|
+
html_options[:class] = "#{html_options[:class]} #{last_class}".strip if last
|
76
81
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
content_tag(tag_name, content, html_options)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
# List item
|
87
|
+
def tag_name
|
88
|
+
'li'
|
84
89
|
end
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
'li'
|
90
|
-
end
|
91
|
+
# Generate the html for the menu
|
92
|
+
def content
|
93
|
+
content = @content
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
+
if @menu_bar.menus.any?
|
96
|
+
# sub-menus have been defined: render markup
|
97
|
+
html = @menu_bar.html
|
95
98
|
|
96
|
-
if
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
content << html
|
102
|
-
else
|
103
|
-
# sub-menu bar will be generated elsewhere
|
104
|
-
request_controller.instance_variable_set(@menu_bar.content_for_variable, html)
|
105
|
-
end
|
99
|
+
if attach_active_submenus? || !selected?
|
100
|
+
content << html
|
101
|
+
else
|
102
|
+
# sub-menu bar will be generated elsewhere
|
103
|
+
request_controller.instance_variable_set(@menu_bar.content_for_variable, html)
|
106
104
|
end
|
107
|
-
|
108
|
-
content
|
109
105
|
end
|
110
106
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
return url, options
|
107
|
+
content
|
108
|
+
end
|
109
|
+
|
110
|
+
# Builds the url based on the options provided in the construction of
|
111
|
+
# the menu
|
112
|
+
def build_url(options = {})
|
113
|
+
# Check if the name given for the menu is a named route
|
114
|
+
if options.blank? && route_options = (named_route(name) || named_route(name, false))
|
115
|
+
options = route_options
|
116
|
+
elsif options.is_a?(Hash)
|
117
|
+
options[:controller] ||= find_controller(options)
|
118
|
+
options[:action] ||= name unless options[:controller] == name
|
119
|
+
options[:only_path] ||= false
|
125
120
|
end
|
126
121
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
122
|
+
url = options.is_a?(Hash) ? url_for(options) : options
|
123
|
+
return url, options
|
124
|
+
end
|
125
|
+
|
126
|
+
# Finds the most likely controller that this menu should link to
|
127
|
+
def find_controller(options)
|
128
|
+
# 1. Specified controller in the menu link options
|
129
|
+
options[:controller] ||
|
130
|
+
# 2. The name of the menu (e.g. products = ProductsController)
|
131
|
+
(begin; "#{name.camelize}Controller".constantize.controller_path; rescue; end) ||
|
132
|
+
# 3. The parent's controller
|
133
|
+
parent_menu && parent_menu.url_options[:controller] ||
|
134
|
+
# 4. The request controller
|
135
|
+
request_controller.class.controller_path
|
136
|
+
end
|
137
|
+
|
138
|
+
# Finds the named route that is being linked to (if that route exists)
|
139
|
+
def named_route(name, include_parent = true)
|
140
|
+
name = "#{parent_menu.name}_#{name}" if parent_menu && include_parent
|
141
|
+
method_name = "hash_for_#{name}_url"
|
138
142
|
|
139
|
-
|
140
|
-
|
141
|
-
name = "#{parent_menu.name}_#{name}" if parent_menu && include_parent
|
142
|
-
method_name = "hash_for_#{name}_url"
|
143
|
-
|
144
|
-
request_controller.send(method_name) if request_controller.respond_to?(method_name)
|
145
|
-
end
|
146
|
-
end
|
143
|
+
request_controller.send(method_name) if request_controller.respond_to?(method_name)
|
144
|
+
end
|
147
145
|
end
|
148
146
|
end
|