simple-navigation 3.12.0 → 3.12.1
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 +4 -0
- data/generators/navigation_config/navigation_config_generator.rb +3 -3
- data/generators/navigation_config/templates/config/navigation.rb +9 -10
- data/init.rb +1 -1
- data/lib/generators/navigation_config/navigation_config_generator.rb +11 -6
- data/lib/simple-navigation.rb +1 -1
- data/lib/simple_navigation.rb +93 -65
- data/lib/simple_navigation/adapters/base.rb +16 -16
- data/lib/simple_navigation/adapters/nanoc.rb +7 -6
- data/lib/simple_navigation/adapters/padrino.rb +5 -7
- data/lib/simple_navigation/adapters/rails.rb +52 -39
- data/lib/simple_navigation/adapters/sinatra.rb +14 -17
- data/lib/simple_navigation/core/configuration.rb +73 -34
- data/lib/simple_navigation/core/item.rb +110 -54
- data/lib/simple_navigation/core/item_adapter.rb +18 -13
- data/lib/simple_navigation/core/item_container.rb +93 -66
- data/lib/simple_navigation/core/items_provider.rb +12 -10
- data/lib/simple_navigation/rails_controller_methods.rb +98 -78
- data/lib/simple_navigation/rendering/helpers.rb +130 -68
- data/lib/simple_navigation/rendering/renderer/base.rb +30 -25
- data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +26 -19
- data/lib/simple_navigation/rendering/renderer/json.rb +11 -13
- data/lib/simple_navigation/rendering/renderer/links.rb +18 -13
- data/lib/simple_navigation/rendering/renderer/list.rb +28 -15
- data/lib/simple_navigation/rendering/renderer/text.rb +7 -12
- data/lib/simple_navigation/version.rb +1 -1
- data/spec/lib/simple_navigation/core/item_adapter_spec.rb +1 -1
- data/spec/lib/simple_navigation/core/item_container_spec.rb +118 -68
- data/spec/lib/simple_navigation_spec.rb +16 -5
- metadata +2 -2
@@ -1,81 +1,150 @@
|
|
1
1
|
module SimpleNavigation
|
2
|
-
|
3
2
|
# View helpers to render the navigation.
|
4
3
|
#
|
5
4
|
# Use render_navigation as following to render your navigation:
|
6
|
-
# * call <tt>render_navigation</tt> without :level option to render your
|
7
|
-
#
|
8
|
-
# * call <tt>render_navigation(:
|
9
|
-
#
|
5
|
+
# * call <tt>render_navigation</tt> without :level option to render your
|
6
|
+
# complete navigation as nested tree.
|
7
|
+
# * call <tt>render_navigation(level: x)</tt> to render a specific
|
8
|
+
# navigation level (e.g. level: 1 to render your primary navigation,
|
9
|
+
# level: 2 to render the sub navigation and so forth)
|
10
|
+
# * call <tt>render_navigation(:level => 2..3)</tt> to render navigation
|
11
|
+
# levels 2 and 3).
|
12
|
+
#
|
13
|
+
# For example, you could use render_navigation(level: 1) to render your
|
14
|
+
# primary navigation as tabs and render_navigation(level: 2..3) to render
|
15
|
+
# the rest of the navigation as a tree in a sidebar.
|
10
16
|
#
|
11
17
|
# ==== Examples (using Haml)
|
12
|
-
# #primary_navigation= render_navigation(:
|
18
|
+
# #primary_navigation= render_navigation(level: 1)
|
13
19
|
#
|
14
|
-
# #sub_navigation= render_navigation(:
|
20
|
+
# #sub_navigation= render_navigation(level: 2)
|
15
21
|
#
|
16
22
|
# #nested_navigation= render_navigation
|
17
23
|
#
|
18
|
-
# #top_navigation= render_navigation(:
|
19
|
-
# #sidebar_navigation= render_navigation(:
|
24
|
+
# #top_navigation= render_navigation(level: 1..2)
|
25
|
+
# #sidebar_navigation= render_navigation(level: 3)
|
20
26
|
module Helpers
|
27
|
+
def self.load_config(options, includer, &block)
|
28
|
+
context = options.delete(:context)
|
29
|
+
SimpleNavigation.init_adapter_from includer
|
30
|
+
SimpleNavigation.load_config context
|
31
|
+
SimpleNavigation::Configuration.eval_config context
|
32
|
+
|
33
|
+
if block_given? || options[:items]
|
34
|
+
SimpleNavigation.config.items(options[:items], &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
if SimpleNavigation.respond_to?(:handle_explicit_navigation)
|
38
|
+
SimpleNavigation.handle_explicit_navigation
|
39
|
+
end
|
40
|
+
|
41
|
+
unless SimpleNavigation.primary_navigation
|
42
|
+
fail 'no primary navigation defined, either use a navigation config ' \
|
43
|
+
'file or pass items directly to render_navigation'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.apply_defaults(options)
|
48
|
+
options[:level] = options.delete(:levels) if options[:levels]
|
49
|
+
{ context: :default, level: :all }.merge(options)
|
50
|
+
end
|
21
51
|
|
22
52
|
# Renders the navigation according to the specified options-hash.
|
23
53
|
#
|
24
54
|
# The following options are supported:
|
25
|
-
# * <tt>:level</tt> - defaults to :all which renders the the sub_navigation
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# * <tt>:
|
55
|
+
# * <tt>:level</tt> - defaults to :all which renders the the sub_navigation
|
56
|
+
# for an active primary_navigation inside that active
|
57
|
+
# primary_navigation item.
|
58
|
+
# Specify a specific level to only render that level of navigation
|
59
|
+
# (e.g. level: 1 for primary_navigation, etc).
|
60
|
+
# Specifiy a Range of levels to render only those specific levels
|
61
|
+
# (e.g. level: 1..2 to render both your first and second levels, maybe
|
62
|
+
# you want to render your third level somewhere else on the page)
|
63
|
+
# * <tt>:expand_all</tt> - defaults to false. If set to true the all
|
64
|
+
# specified levels will be rendered as a fully expanded
|
65
|
+
# tree (always open). This is useful for javascript menus like Superfish.
|
66
|
+
# * <tt>:context</tt> - specifies the context for which you would render
|
67
|
+
# the navigation. Defaults to :default which loads the default
|
68
|
+
# navigation.rb (i.e. config/navigation.rb).
|
69
|
+
# If you specify a context then the plugin tries to load the configuration
|
70
|
+
# file for that context, e.g. if you call
|
71
|
+
# <tt>render_navigation(context: :admin)</tt> the file
|
72
|
+
# config/admin_navigation.rb will be loaded and used for rendering
|
73
|
+
# the navigation.
|
74
|
+
# * <tt>:items</tt> - you can specify the items directly (e.g. if items are
|
75
|
+
# dynamically generated from database).
|
76
|
+
# See SimpleNavigation::ItemsProvider for documentation on what to
|
77
|
+
# provide as items.
|
78
|
+
# * <tt>:renderer</tt> - specify the renderer to be used for rendering the
|
79
|
+
# navigation. Either provide the Class or a symbol matching a registered
|
80
|
+
# renderer. Defaults to :list (html list renderer).
|
34
81
|
#
|
35
|
-
# Instead of using the <tt>:items</tt> option, a block can be passed to
|
82
|
+
# Instead of using the <tt>:items</tt> option, a block can be passed to
|
83
|
+
# specify the items dynamically
|
36
84
|
#
|
85
|
+
# ==== Examples
|
37
86
|
# render_navigation do |menu|
|
38
87
|
# menu.item :posts, "Posts", posts_path
|
39
88
|
# end
|
40
89
|
#
|
41
|
-
def render_navigation(options={}
|
42
|
-
container = active_navigation_item_container(options
|
90
|
+
def render_navigation(options = {}, &block)
|
91
|
+
container = active_navigation_item_container(options, &block)
|
43
92
|
container && container.render(options)
|
44
93
|
end
|
45
94
|
|
46
|
-
# Returns the name of the currently active navigation item belonging to the
|
95
|
+
# Returns the name of the currently active navigation item belonging to the
|
96
|
+
# specified level.
|
47
97
|
#
|
48
98
|
# See Helpers#active_navigation_item for supported options.
|
49
99
|
#
|
50
|
-
# Returns an empty string if no active item can be found for the specified
|
51
|
-
|
52
|
-
|
100
|
+
# Returns an empty string if no active item can be found for the specified
|
101
|
+
# options
|
102
|
+
def active_navigation_item_name(options = {})
|
103
|
+
active_navigation_item(options, '') do |item|
|
104
|
+
item.name(apply_generator: false)
|
105
|
+
end
|
53
106
|
end
|
54
107
|
|
55
|
-
# Returns the key of the currently active navigation item belonging to the
|
108
|
+
# Returns the key of the currently active navigation item belonging to the
|
109
|
+
# specified level.
|
56
110
|
#
|
57
111
|
# See Helpers#active_navigation_item for supported options.
|
58
112
|
#
|
59
|
-
# Returns <tt>nil</tt> if no active item can be found for the specified
|
60
|
-
|
61
|
-
|
113
|
+
# Returns <tt>nil</tt> if no active item can be found for the specified
|
114
|
+
# options
|
115
|
+
def active_navigation_item_key(options = {})
|
116
|
+
active_navigation_item(options, &:key)
|
62
117
|
end
|
63
118
|
|
64
|
-
# Returns the currently active navigation item belonging to the specified
|
119
|
+
# Returns the currently active navigation item belonging to the specified
|
120
|
+
# level.
|
65
121
|
#
|
66
122
|
# The following options are supported:
|
67
|
-
# * <tt>:level</tt> - defaults to :all which returns the
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# * <tt>:
|
123
|
+
# * <tt>:level</tt> - defaults to :all which returns the
|
124
|
+
# most specific/deepest selected item (the leaf).
|
125
|
+
# Specify a specific level to only look for the selected item in the
|
126
|
+
# specified level of navigation
|
127
|
+
# (e.g. level: 1 for primary_navigation, etc).
|
128
|
+
# * <tt>:context</tt> - specifies the context for which you would like to
|
129
|
+
# find the active navigation item. Defaults to :default which loads the
|
130
|
+
# default navigation.rb (i.e. config/navigation.rb).
|
131
|
+
# If you specify a context then the plugin tries to load the configuration
|
132
|
+
# file for that context, e.g. if you call
|
133
|
+
# <tt>active_navigation_item_name(context: :admin)</tt> the file
|
134
|
+
# config/admin_navigation.rb will be loaded and used for searching the
|
135
|
+
# active item.
|
136
|
+
# * <tt>:items</tt> - you can specify the items directly (e.g. if items are
|
137
|
+
# dynamically generated from database).
|
138
|
+
# See SimpleNavigation::ItemsProvider for documentation on what to provide
|
139
|
+
# as items.
|
73
140
|
#
|
74
141
|
# Returns the supplied <tt>value_for_nil</tt> object (<tt>nil</tt>
|
75
142
|
# by default) if no active item can be found for the specified
|
76
143
|
# options
|
77
|
-
def active_navigation_item(options={},value_for_nil = nil)
|
78
|
-
|
144
|
+
def active_navigation_item(options = {}, value_for_nil = nil)
|
145
|
+
if options[:level].nil? || options[:level] == :all
|
146
|
+
options[:level] = :leaves
|
147
|
+
end
|
79
148
|
container = active_navigation_item_container(options)
|
80
149
|
if container && (item = container.selected_item)
|
81
150
|
block_given? ? yield(item) : item
|
@@ -84,40 +153,33 @@ module SimpleNavigation
|
|
84
153
|
end
|
85
154
|
end
|
86
155
|
|
87
|
-
# Returns the currently active item container belonging to the specified
|
156
|
+
# Returns the currently active item container belonging to the specified
|
157
|
+
# level.
|
88
158
|
#
|
89
159
|
# The following options are supported:
|
90
|
-
# * <tt>:level</tt> - defaults to :all which returns the
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
# * <tt>:
|
160
|
+
# * <tt>:level</tt> - defaults to :all which returns the
|
161
|
+
# least specific/shallowest selected item.
|
162
|
+
# Specify a specific level to only look for the selected item in the
|
163
|
+
# specified level of navigation
|
164
|
+
# (e.g. level: 1 for primary_navigation, etc).
|
165
|
+
# * <tt>:context</tt> - specifies the context for which you would like to
|
166
|
+
# find the active navigation item. Defaults to :default which loads the
|
167
|
+
# default navigation.rb (i.e. config/navigation.rb).
|
168
|
+
# If you specify a context then the plugin tries to load the configuration
|
169
|
+
# file for that context, e.g. if you call
|
170
|
+
# <tt>active_navigation_item_name(context: :admin)</tt> the file
|
171
|
+
# config/admin_navigation.rb will be loaded and used for searching the
|
172
|
+
# active item.
|
173
|
+
# * <tt>:items</tt> - you can specify the items directly (e.g. if items are
|
174
|
+
# dynamically generated from database).
|
175
|
+
# See SimpleNavigation::ItemsProvider for documentation on what to provide
|
176
|
+
# as items.
|
96
177
|
#
|
97
178
|
# Returns <tt>nil</tt> if no active item container can be found
|
98
|
-
def active_navigation_item_container(options={}
|
99
|
-
options = SimpleNavigation::Helpers
|
100
|
-
SimpleNavigation::Helpers
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
class << self
|
105
|
-
def load_config(options,includer,&block)
|
106
|
-
ctx = options.delete(:context)
|
107
|
-
SimpleNavigation.init_adapter_from includer
|
108
|
-
SimpleNavigation.load_config(ctx)
|
109
|
-
SimpleNavigation::Configuration.eval_config(ctx)
|
110
|
-
if block_given? || options[:items]
|
111
|
-
SimpleNavigation.config.items(options[:items],&block)
|
112
|
-
end
|
113
|
-
SimpleNavigation.handle_explicit_navigation if SimpleNavigation.respond_to?(:handle_explicit_navigation)
|
114
|
-
raise "no primary navigation defined, either use a navigation config file or pass items directly to render_navigation" unless SimpleNavigation.primary_navigation
|
115
|
-
end
|
116
|
-
|
117
|
-
def apply_defaults(options)
|
118
|
-
options[:level] = options.delete(:levels) if options[:levels]
|
119
|
-
{:context => :default, :level => :all}.merge(options)
|
120
|
-
end
|
179
|
+
def active_navigation_item_container(options = {}, &block)
|
180
|
+
options = SimpleNavigation::Helpers.apply_defaults(options)
|
181
|
+
SimpleNavigation::Helpers.load_config(options, self, &block)
|
182
|
+
SimpleNavigation.active_item_container_for(options[:level])
|
121
183
|
end
|
122
184
|
end
|
123
185
|
end
|
@@ -2,17 +2,17 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
module SimpleNavigation
|
4
4
|
module Renderer
|
5
|
-
|
6
5
|
# This is the base class for all renderers.
|
7
6
|
#
|
8
|
-
# A renderer is responsible for rendering an ItemContainer and its
|
7
|
+
# A renderer is responsible for rendering an ItemContainer and its
|
8
|
+
# containing items to HTML.
|
9
9
|
class Base
|
10
10
|
extend Forwardable
|
11
|
-
|
12
|
-
attr_reader :
|
13
|
-
|
11
|
+
|
12
|
+
attr_reader :adapter, :options
|
13
|
+
|
14
14
|
def_delegators :adapter, :link_to, :content_tag
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(options) #:nodoc:
|
17
17
|
@options = options
|
18
18
|
@adapter = SimpleNavigation.adapter
|
@@ -35,31 +35,28 @@ module SimpleNavigation
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def render_sub_navigation_for(item)
|
38
|
-
item.sub_navigation.render(
|
38
|
+
item.sub_navigation.render(options)
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
# Renders the specified ItemContainer to HTML.
|
42
42
|
#
|
43
|
-
# When implementing a renderer, please consider to call
|
44
|
-
# whether an item's sub_navigation
|
45
|
-
#
|
43
|
+
# When implementing a renderer, please consider to call
|
44
|
+
# include_sub_navigation? to determine whether an item's sub_navigation
|
45
|
+
# should be rendered or not.
|
46
46
|
def render(item_container)
|
47
|
-
|
47
|
+
fail NotImplementedError, 'subclass responsibility'
|
48
48
|
end
|
49
49
|
|
50
50
|
protected
|
51
51
|
|
52
52
|
def consider_sub_navigation?(item)
|
53
|
-
return false
|
53
|
+
return false unless item.sub_navigation
|
54
|
+
|
54
55
|
case level
|
55
|
-
when :all
|
56
|
-
|
57
|
-
|
58
|
-
return false
|
59
|
-
when Range
|
60
|
-
return item.sub_navigation.level <= level.max
|
56
|
+
when :all then true
|
57
|
+
when Range then item.sub_navigation.level <= level.max
|
58
|
+
else false
|
61
59
|
end
|
62
|
-
false
|
63
60
|
end
|
64
61
|
|
65
62
|
def expand_sub_navigation?(item)
|
@@ -92,16 +89,24 @@ module SimpleNavigation
|
|
92
89
|
end
|
93
90
|
|
94
91
|
# Extracts the options relevant for the generated link
|
95
|
-
#
|
96
92
|
def link_options_for(item)
|
97
|
-
special_options = {
|
93
|
+
special_options = {
|
94
|
+
method: item.method,
|
95
|
+
class: item.selected_class
|
96
|
+
}.reject { |_, v| v.nil? }
|
97
|
+
|
98
98
|
link_options = item.html_options[:link]
|
99
|
+
|
99
100
|
return special_options unless link_options
|
101
|
+
|
100
102
|
opts = special_options.merge(link_options)
|
101
|
-
|
102
|
-
|
103
|
+
|
104
|
+
classes = [link_options[:class], item.selected_class]
|
105
|
+
classes = classes.flatten.compact.join(' ')
|
106
|
+
opts[:class] = classes unless classes.empty?
|
107
|
+
|
103
108
|
opts
|
104
|
-
end
|
109
|
+
end
|
105
110
|
end
|
106
111
|
end
|
107
112
|
end
|
@@ -1,38 +1,40 @@
|
|
1
1
|
module SimpleNavigation
|
2
2
|
module Renderer
|
3
|
-
|
4
|
-
#
|
3
|
+
# Renders an ItemContainer as a <div> element and its containing items as
|
4
|
+
# <a> elements.
|
5
5
|
# It only renders 'selected' elements.
|
6
6
|
#
|
7
|
-
# By default, the renderer sets the item's key as dom_id for the rendered
|
8
|
-
#
|
9
|
-
#
|
7
|
+
# By default, the renderer sets the item's key as dom_id for the rendered
|
8
|
+
# <a> element unless the config option <tt>autogenerate_item_ids</tt> is
|
9
|
+
# set to false.
|
10
10
|
#
|
11
|
+
# The id can also be explicitely specified by setting the id in the
|
12
|
+
# html-options of the 'item' method in the config/navigation.rb file.
|
13
|
+
# The ItemContainer's dom_attributes are applied to the surrounding <div>
|
14
|
+
# element.
|
11
15
|
class Breadcrumbs < SimpleNavigation::Renderer::Base
|
12
|
-
|
13
16
|
def render(item_container)
|
14
17
|
content = a_tags(item_container).join(join_with)
|
15
18
|
content_tag(:div,
|
16
|
-
|
17
|
-
|
19
|
+
prefix_for(content) + content,
|
20
|
+
item_container.dom_attributes)
|
18
21
|
end
|
19
22
|
|
20
23
|
protected
|
21
24
|
|
22
25
|
def a_tags(item_container)
|
23
|
-
item_container.items.
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
item_container.items.each_with_object([]) do |item, list|
|
27
|
+
next unless item.selected?
|
28
|
+
list << tag_for(item)
|
29
|
+
|
30
|
+
if include_sub_navigation?(item)
|
31
|
+
list.concat a_tags(item.sub_navigation)
|
29
32
|
end
|
30
|
-
list
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
36
|
def join_with
|
35
|
-
@join_with ||= options[:join_with] ||
|
37
|
+
@join_with ||= options[:join_with] || ' '
|
36
38
|
end
|
37
39
|
|
38
40
|
def suppress_link?(item)
|
@@ -40,7 +42,11 @@ module SimpleNavigation
|
|
40
42
|
end
|
41
43
|
|
42
44
|
def prefix_for(content)
|
43
|
-
content.empty?
|
45
|
+
if !content.empty? && options[:prefix]
|
46
|
+
options[:prefix]
|
47
|
+
else
|
48
|
+
''
|
49
|
+
end
|
44
50
|
end
|
45
51
|
|
46
52
|
# Extracts the options relevant for the generated link
|
@@ -48,10 +54,11 @@ module SimpleNavigation
|
|
48
54
|
def link_options_for(item)
|
49
55
|
if options[:allow_classes_and_ids]
|
50
56
|
opts = super
|
51
|
-
opts[:id]
|
57
|
+
opts[:id] &&= "breadcrumb_#{opts[:id]}"
|
52
58
|
opts
|
53
59
|
else
|
54
|
-
|
60
|
+
html_options = item.html_options.except(:class, :id)
|
61
|
+
{ method: item.method }.merge(html_options)
|
55
62
|
end
|
56
63
|
end
|
57
64
|
end
|
@@ -1,29 +1,27 @@
|
|
1
1
|
module SimpleNavigation
|
2
2
|
module Renderer
|
3
|
-
|
4
|
-
#
|
3
|
+
# Renders the navigation items as a object tree serialized as a json string,
|
4
|
+
# can also output raw ruby Hashes
|
5
5
|
class Json < SimpleNavigation::Renderer::Base
|
6
|
-
|
7
6
|
def render(item_container)
|
8
7
|
results = hash_render(item_container)
|
9
|
-
results
|
10
|
-
results
|
8
|
+
options[:as_hash] ? results : results.to_json
|
11
9
|
end
|
12
10
|
|
13
11
|
private
|
14
12
|
|
15
13
|
def hash_render(item_container)
|
16
|
-
return nil
|
14
|
+
return nil unless item_container
|
15
|
+
|
17
16
|
item_container.items.map do |item|
|
18
|
-
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
17
|
+
{
|
18
|
+
items: hash_render(item.sub_navigation),
|
19
|
+
name: item.name,
|
20
|
+
selected: item.selected?,
|
21
|
+
url: item.url
|
23
22
|
}
|
24
|
-
end
|
23
|
+
end
|
25
24
|
end
|
26
|
-
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|