jordanyeo-simple-navigation 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +265 -0
- data/Gemfile +17 -0
- data/README +22 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/generators/navigation_config/USAGE +1 -0
- data/generators/navigation_config/navigation_config_generator.rb +8 -0
- data/generators/navigation_config/templates/config/navigation.rb +76 -0
- data/lib/generators/navigation_config/navigation_config_generator.rb +12 -0
- data/lib/simple-navigation.rb +1 -0
- data/lib/simple_navigation.rb +167 -0
- data/lib/simple_navigation/adapters.rb +10 -0
- data/lib/simple_navigation/adapters/base.rb +37 -0
- data/lib/simple_navigation/adapters/nanoc.rb +45 -0
- data/lib/simple_navigation/adapters/padrino.rb +20 -0
- data/lib/simple_navigation/adapters/rails.rb +93 -0
- data/lib/simple_navigation/adapters/sinatra.rb +69 -0
- data/lib/simple_navigation/core.rb +5 -0
- data/lib/simple_navigation/core/configuration.rb +72 -0
- data/lib/simple_navigation/core/item.rb +144 -0
- data/lib/simple_navigation/core/item_adapter.rb +63 -0
- data/lib/simple_navigation/core/item_container.rb +147 -0
- data/lib/simple_navigation/core/items_provider.rb +35 -0
- data/lib/simple_navigation/rails_controller_methods.rb +144 -0
- data/lib/simple_navigation/rendering.rb +12 -0
- data/lib/simple_navigation/rendering/helpers.rb +123 -0
- data/lib/simple_navigation/rendering/renderer/base.rb +107 -0
- data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +59 -0
- data/lib/simple_navigation/rendering/renderer/json.rb +29 -0
- data/lib/simple_navigation/rendering/renderer/links.rb +32 -0
- data/lib/simple_navigation/rendering/renderer/list.rb +29 -0
- data/lib/simple_navigation/rendering/renderer/text.rb +26 -0
- data/rails/init.rb +1 -0
- data/spec/lib/simple_navigation/adapters/padrino_spec.rb +31 -0
- data/spec/lib/simple_navigation/adapters/rails_spec.rb +287 -0
- data/spec/lib/simple_navigation/adapters/sinatra_spec.rb +80 -0
- data/spec/lib/simple_navigation/core/configuration_spec.rb +128 -0
- data/spec/lib/simple_navigation/core/item_adapter_spec.rb +212 -0
- data/spec/lib/simple_navigation/core/item_container_spec.rb +451 -0
- data/spec/lib/simple_navigation/core/item_spec.rb +566 -0
- data/spec/lib/simple_navigation/core/items_provider_spec.rb +60 -0
- data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +249 -0
- data/spec/lib/simple_navigation/rendering/helpers_spec.rb +276 -0
- data/spec/lib/simple_navigation/rendering/renderer/base_spec.rb +199 -0
- data/spec/lib/simple_navigation/rendering/renderer/breadcrumbs_spec.rb +101 -0
- data/spec/lib/simple_navigation/rendering/renderer/json_spec.rb +48 -0
- data/spec/lib/simple_navigation/rendering/renderer/links_spec.rb +64 -0
- data/spec/lib/simple_navigation/rendering/renderer/list_spec.rb +211 -0
- data/spec/lib/simple_navigation/rendering/renderer/text_spec.rb +41 -0
- data/spec/lib/simple_navigation_spec.rb +307 -0
- data/spec/spec_helper.rb +108 -0
- metadata +199 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module SimpleNavigation
|
4
|
+
|
5
|
+
# Responsible for evaluating and handling the config/navigation.rb file.
|
6
|
+
class Configuration
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
attr_accessor :renderer, :selected_class, :active_leaf_class, :autogenerate_item_ids, :id_generator, :auto_highlight, :name_generator
|
10
|
+
attr_reader :primary_navigation
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Evals the config_file for the given navigation_context
|
15
|
+
def eval_config(navigation_context = :default)
|
16
|
+
SimpleNavigation.context_for_eval.instance_eval(SimpleNavigation.config_files[navigation_context])
|
17
|
+
end
|
18
|
+
|
19
|
+
# Starts processing the configuration
|
20
|
+
def run(&block)
|
21
|
+
block.call Configuration.instance
|
22
|
+
end
|
23
|
+
|
24
|
+
end #class << self
|
25
|
+
|
26
|
+
# Sets the config's default-settings
|
27
|
+
def initialize
|
28
|
+
@renderer = SimpleNavigation.default_renderer || SimpleNavigation::Renderer::List
|
29
|
+
@selected_class = 'selected'
|
30
|
+
@active_leaf_class = 'simple-navigation-active-leaf'
|
31
|
+
@autogenerate_item_ids = true
|
32
|
+
@id_generator = Proc.new {|id| id.to_s }
|
33
|
+
@name_generator = Proc.new {|name| name}
|
34
|
+
@auto_highlight = true
|
35
|
+
end
|
36
|
+
|
37
|
+
# This is the main method for specifying the navigation items. It can be used in two ways:
|
38
|
+
#
|
39
|
+
# 1. Declaratively specify your items in the config/navigation.rb file using a block. It then yields an SimpleNavigation::ItemContainer for adding navigation items.
|
40
|
+
# 1. Directly provide your items to the method (e.g. when loading your items from the database).
|
41
|
+
#
|
42
|
+
# ==== Example for block style (configuration file)
|
43
|
+
# config.items do |primary|
|
44
|
+
# primary.item :my_item, 'My item', my_item_path
|
45
|
+
# ...
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# ==== To consider when directly providing items
|
49
|
+
# items_provider should be:
|
50
|
+
# * a methodname (as symbol) that returns your items. The method needs to be available in the view (i.e. a helper method)
|
51
|
+
# * an object that responds to :items
|
52
|
+
# * an enumerable containing your items
|
53
|
+
# The items you specify have to fullfill certain requirements. See SimpleNavigation::ItemAdapter for more details.
|
54
|
+
#
|
55
|
+
def items(items_provider=nil, &block)
|
56
|
+
raise 'please specify either items_provider or block, but not both' if (items_provider && block) || (items_provider.nil? && block.nil?)
|
57
|
+
@primary_navigation = ItemContainer.new
|
58
|
+
if block
|
59
|
+
block.call @primary_navigation
|
60
|
+
else
|
61
|
+
@primary_navigation.items = SimpleNavigation::ItemsProvider.new(items_provider).items
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns true if the config_file has already been evaluated.
|
66
|
+
def loaded?
|
67
|
+
!@primary_navigation.nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
|
3
|
+
# Represents an item in your navigation. Gets generated by the item method in the config-file.
|
4
|
+
class Item
|
5
|
+
attr_reader :key, :url, :sub_navigation, :method, :highlights_on
|
6
|
+
attr_writer :html_options
|
7
|
+
|
8
|
+
# see ItemContainer#item
|
9
|
+
#
|
10
|
+
# The subnavigation (if any) is either provided by a block or passed in directly as <tt>items</tt>
|
11
|
+
def initialize(container, key, name, url_or_options = {}, options_or_nil={}, items=nil, &sub_nav_block)
|
12
|
+
@container = container
|
13
|
+
options = setup_url_and_options(url_or_options, options_or_nil)
|
14
|
+
@container.dom_class = options.delete(:container_class) if options[:container_class]
|
15
|
+
@container.dom_id = options.delete(:container_id) if options[:container_id]
|
16
|
+
@container.selected_class = options.delete(:selected_class) if options[:selected_class]
|
17
|
+
@key = key
|
18
|
+
@method = options.delete(:method)
|
19
|
+
@name = name
|
20
|
+
if sub_nav_block || items
|
21
|
+
@sub_navigation = ItemContainer.new(@container.level + 1)
|
22
|
+
sub_nav_block.call @sub_navigation if sub_nav_block
|
23
|
+
@sub_navigation.items = items if items
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the item's name. If option :apply_generator is set to true (default),
|
28
|
+
# the name will be passed to the name_generator specified in the configuration.
|
29
|
+
#
|
30
|
+
def name(options = {})
|
31
|
+
options.reverse_merge!(:apply_generator => true)
|
32
|
+
if (options[:apply_generator])
|
33
|
+
SimpleNavigation.config.name_generator.call(@name)
|
34
|
+
else
|
35
|
+
@name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns true if this navigation item should be rendered as 'selected'.
|
40
|
+
# An item is selected if
|
41
|
+
#
|
42
|
+
# * it has been explicitly selected in a controller or
|
43
|
+
# * it has a subnavigation and one of its subnavigation items is selected or
|
44
|
+
# * its url matches the url of the current request (auto highlighting)
|
45
|
+
#
|
46
|
+
def selected?
|
47
|
+
@selected = @selected || selected_by_config? || selected_by_subnav? || selected_by_condition?
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the html-options hash for the item, i.e. the options specified for this item in the config-file.
|
51
|
+
# It also adds the 'selected' class to the list of classes if necessary.
|
52
|
+
def html_options
|
53
|
+
default_options = self.autogenerate_item_ids? ? {:id => autogenerated_item_id} : {}
|
54
|
+
options = default_options.merge(@html_options)
|
55
|
+
options[:class] = [@html_options[:class], self.selected_class, self.active_leaf_class].flatten.compact.join(' ')
|
56
|
+
options.delete(:class) if options[:class].nil? || options[:class] == ''
|
57
|
+
options
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the configured active_leaf_class if the item is the selected leaf,
|
61
|
+
# nil otherwise
|
62
|
+
def active_leaf_class
|
63
|
+
!selected_by_subnav? && selected_by_condition? ? SimpleNavigation.config.active_leaf_class : nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the configured selected_class if the item is selected,
|
67
|
+
# nil otherwise
|
68
|
+
def selected_class
|
69
|
+
selected? ? (@container.selected_class || SimpleNavigation.config.selected_class) : nil
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# Returns true if item has a subnavigation and the sub_navigation is selected
|
75
|
+
def selected_by_subnav?
|
76
|
+
sub_navigation && sub_navigation.selected?
|
77
|
+
end
|
78
|
+
|
79
|
+
def selected_by_config?
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns true if the item's url matches the request's current url.
|
84
|
+
def selected_by_condition?
|
85
|
+
if highlights_on
|
86
|
+
case highlights_on
|
87
|
+
when Regexp
|
88
|
+
SimpleNavigation.request_uri =~ highlights_on
|
89
|
+
when Proc
|
90
|
+
highlights_on.call
|
91
|
+
when :subpath
|
92
|
+
!!(SimpleNavigation.request_uri =~ /^#{Regexp.escape url_without_anchor}(\/|$|\?)/i)
|
93
|
+
else
|
94
|
+
raise ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
|
95
|
+
end
|
96
|
+
elsif auto_highlight?
|
97
|
+
!!(root_path_match? || (url_without_anchor && SimpleNavigation.current_page?(url_without_anchor)))
|
98
|
+
else
|
99
|
+
false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns true if both the item's url and the request's url are root_path
|
104
|
+
def root_path_match?
|
105
|
+
url == '/' && SimpleNavigation.request_path == '/'
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns true if the item's id should be added to the rendered output.
|
109
|
+
def autogenerate_item_ids?
|
110
|
+
SimpleNavigation.config.autogenerate_item_ids
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns the item's id which is added to the rendered output.
|
114
|
+
def autogenerated_item_id
|
115
|
+
SimpleNavigation.config.id_generator.call(key)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Return true if auto_highlight is on for this item.
|
119
|
+
def auto_highlight?
|
120
|
+
SimpleNavigation.config.auto_highlight && @container.auto_highlight
|
121
|
+
end
|
122
|
+
|
123
|
+
def url_without_anchor
|
124
|
+
url && url.split('#').first
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
def setup_url_and_options(url_or_options, options_or_nil)
|
129
|
+
options = options_or_nil
|
130
|
+
url = url_or_options
|
131
|
+
case url_or_options
|
132
|
+
when Hash
|
133
|
+
# url_or_options is options (there is no url)
|
134
|
+
options = url_or_options
|
135
|
+
when Proc
|
136
|
+
@url = url.call
|
137
|
+
else
|
138
|
+
@url = url
|
139
|
+
end
|
140
|
+
@highlights_on = options.delete(:highlights_on)
|
141
|
+
@html_options = options
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module SimpleNavigation
|
4
|
+
|
5
|
+
# This class acts as an adapter to items that are not defined using the DSL in the config/navigation.rb, but directly provided inside the application.
|
6
|
+
# When defining the items that way, every item you provide needs to define the following methods:
|
7
|
+
#
|
8
|
+
# * <tt>key</tt>
|
9
|
+
# * <tt>name</tt>
|
10
|
+
# * <tt>url</tt>
|
11
|
+
#
|
12
|
+
# and optionally
|
13
|
+
#
|
14
|
+
# * <tt>options</tt>
|
15
|
+
# * <tt>items</tt> - if one of your items has a subnavigation it must respond to <tt>items</tt> providing the subnavigation.
|
16
|
+
#
|
17
|
+
# You can also specify your items as a list of hashes. The hashes will be converted to objects automatically.
|
18
|
+
# The hashes representing the items obviously must have the keys :key, :name and :url and optionally the keys :options and :items.
|
19
|
+
#
|
20
|
+
# See SimpleNavigation::ItemContainer#item for the purpose of these methods.
|
21
|
+
class ItemAdapter
|
22
|
+
extend Forwardable
|
23
|
+
|
24
|
+
def_delegators :item, :key, :name, :url
|
25
|
+
|
26
|
+
attr_reader :item
|
27
|
+
|
28
|
+
def initialize(item)
|
29
|
+
@item = item.is_a?(Hash) ? to_object(item) : item
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the options for this item. If the wrapped item does not implement an options method, an empty hash is returned.
|
33
|
+
def options
|
34
|
+
@item.respond_to?(:options) ? @item.options : {}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the items (subnavigation) for this item if it responds to :items and the items-collection is not empty. Returns nil otherwise.
|
38
|
+
def items
|
39
|
+
(@item.respond_to?(:items) && !(@item.items.nil? || @item.items.empty?)) ? @item.items : nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Converts this Item into a SimpleNavigation::Item
|
43
|
+
def to_simple_navigation_item(item_container)
|
44
|
+
SimpleNavigation::Item.new(item_container, key, name, url, options, items)
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# Converts the specified hash into an object. Each key will be added as method.
|
50
|
+
#
|
51
|
+
def to_object(hash)
|
52
|
+
mod = Module.new do
|
53
|
+
hash.each_pair do |key, value|
|
54
|
+
define_method key do
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
Object.new.extend(mod)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
|
3
|
+
# Holds the Items for a navigation 'level'.
|
4
|
+
class ItemContainer
|
5
|
+
|
6
|
+
attr_reader :items, :level
|
7
|
+
attr_accessor :renderer, :dom_id, :dom_class, :auto_highlight, :selected_class
|
8
|
+
|
9
|
+
def initialize(level=1) #:nodoc:
|
10
|
+
@level = level
|
11
|
+
@items = []
|
12
|
+
@renderer = SimpleNavigation.config.renderer
|
13
|
+
@auto_highlight = true
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates a new navigation item.
|
17
|
+
#
|
18
|
+
# The <tt>key</tt> is a symbol which uniquely defines your navigation item in the scope of the primary_navigation or the sub_navigation.
|
19
|
+
#
|
20
|
+
# The <tt>name</tt> will be displayed in the rendered navigation. This can also be a call to your I18n-framework.
|
21
|
+
#
|
22
|
+
# The <tt>url</tt> is the address that the generated item points to. You can also use url_helpers (named routes, restful routes helper, url_for etc.) <tt>url</tt> is optional - items without URLs should not be rendered as links.
|
23
|
+
#
|
24
|
+
# The <tt>options</tt> can be used to specify the following things:
|
25
|
+
# * <tt>any html_attributes</tt> - will be included in the rendered navigation item (e.g. id, class etc.)
|
26
|
+
# * <tt>:if</tt> - Specifies a proc to call to determine if the item should
|
27
|
+
# be rendered (e.g. <tt>:if => Proc.new { current_user.admin? }</tt>). The
|
28
|
+
# proc should evaluate to a true or false value and is evaluated in the context of the view.
|
29
|
+
# * <tt>:unless</tt> - Specifies a proc to call to determine if the item should not
|
30
|
+
# be rendered (e.g. <tt>:unless => Proc.new { current_user.admin? }</tt>). The
|
31
|
+
# proc should evaluate to a true or false value and is evaluated in the context of the view.
|
32
|
+
# * <tt>:method</tt> - Specifies the http-method for the generated link - default is :get.
|
33
|
+
# * <tt>:highlights_on</tt> - if autohighlighting is turned off and/or you want to explicitly specify
|
34
|
+
# when the item should be highlighted, you can set a regexp which is matched againstthe current URI.
|
35
|
+
#
|
36
|
+
# The <tt>block</tt> - if specified - will hold the item's sub_navigation.
|
37
|
+
def item(key, name, url_or_options = {}, options_or_nil = {}, &block)
|
38
|
+
options = url_or_options.is_a?(Hash) ? url_or_options : options_or_nil
|
39
|
+
(@items << SimpleNavigation::Item.new(self, key, name, url_or_options, options_or_nil, nil, &block)) if should_add_item?(options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def items=(items)
|
43
|
+
items.each do |item|
|
44
|
+
item = SimpleNavigation::ItemAdapter.new(item)
|
45
|
+
(@items << item.to_simple_navigation_item(self)) if should_add_item?(item.options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the Item with the specified key, nil otherwise.
|
50
|
+
#
|
51
|
+
def [](navi_key)
|
52
|
+
items.find {|i| i.key == navi_key}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the level of the item specified by navi_key.
|
56
|
+
# Recursively works its way down the item's sub_navigations if the desired item is not found directly in this container's items.
|
57
|
+
# Returns nil item cannot be found.
|
58
|
+
#
|
59
|
+
def level_for_item(navi_key)
|
60
|
+
my_item = self[navi_key]
|
61
|
+
return self.level if my_item
|
62
|
+
items.each do |i|
|
63
|
+
if i.sub_navigation
|
64
|
+
level = i.sub_navigation.level_for_item(navi_key)
|
65
|
+
return level unless level.nil?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
return nil
|
69
|
+
end
|
70
|
+
|
71
|
+
# Renders the items in this ItemContainer using the configured renderer.
|
72
|
+
#
|
73
|
+
# The options are the same as in the view's render_navigation call (they get passed on)
|
74
|
+
def render(options={})
|
75
|
+
renderer_instance = if options[:renderer]
|
76
|
+
if options[:renderer].instance_of?(Symbol) && SimpleNavigation.registered_renderers.key?(options[:renderer])
|
77
|
+
SimpleNavigation.registered_renderers[options[:renderer]].new(options)
|
78
|
+
else
|
79
|
+
options[:renderer].new(options)
|
80
|
+
end
|
81
|
+
else
|
82
|
+
self.renderer.new(options)
|
83
|
+
end
|
84
|
+
renderer_instance.render(self)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns true if any of this container's items is selected.
|
88
|
+
#
|
89
|
+
def selected?
|
90
|
+
items.any? {|i| i.selected?}
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the currently selected item, nil if no item is selected.
|
94
|
+
#
|
95
|
+
def selected_item
|
96
|
+
items.find {|i| i.selected?}
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the active item_container for the specified level
|
100
|
+
# (recursively looks up items in selected sub_navigation if level is deeper than this container's level).
|
101
|
+
#
|
102
|
+
def active_item_container_for(desired_level)
|
103
|
+
return self if self.level == desired_level
|
104
|
+
return nil unless selected_sub_navigation?
|
105
|
+
return selected_item.sub_navigation.active_item_container_for(desired_level)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns the deepest possible active item_container.
|
109
|
+
# (recursively searches in the sub_navigation if this container has a selected sub_navigation).
|
110
|
+
def active_leaf_container
|
111
|
+
if selected_sub_navigation?
|
112
|
+
selected_item.sub_navigation.active_leaf_container
|
113
|
+
else
|
114
|
+
self
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns true if there are no items defined for this container.
|
119
|
+
def empty?
|
120
|
+
items.empty?
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def selected_sub_navigation?
|
126
|
+
!!(selected_item && selected_item.sub_navigation)
|
127
|
+
end
|
128
|
+
|
129
|
+
# partially borrowed from ActionSupport::Callbacks
|
130
|
+
def should_add_item?(options) #:nodoc:
|
131
|
+
[options.delete(:if)].flatten.compact.all? { |m| evaluate_method(m) } &&
|
132
|
+
![options.delete(:unless)].flatten.compact.any? { |m| evaluate_method(m) }
|
133
|
+
end
|
134
|
+
|
135
|
+
# partially borrowed from ActionSupport::Callbacks
|
136
|
+
def evaluate_method(method) #:nodoc:
|
137
|
+
case method
|
138
|
+
when Proc, Method
|
139
|
+
method.call
|
140
|
+
else
|
141
|
+
raise ArgumentError, ":if or :unless must be procs or lambdas"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
|
3
|
+
# Acts as a proxy to navigation items that are passed into the SimpleNavigation::Configuration#items method. It hides the logic
|
4
|
+
# for finding items from the Configuration object.
|
5
|
+
#
|
6
|
+
class ItemsProvider
|
7
|
+
|
8
|
+
attr_reader :provider
|
9
|
+
|
10
|
+
# It accepts the following types of provider:
|
11
|
+
# * methodname as symbol - the specified method should return the relevant items and has to be available in the view (a helper method)
|
12
|
+
# * object that responds to :items
|
13
|
+
# * enumerable object that represents the items
|
14
|
+
#
|
15
|
+
# See SimpleNavigation::ItemAdapter for the requirements that need to be fulfilled by the provided items.
|
16
|
+
#
|
17
|
+
def initialize(provider)
|
18
|
+
@provider = provider
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the navigation items
|
22
|
+
def items
|
23
|
+
if provider.instance_of?(Symbol)
|
24
|
+
SimpleNavigation.context_for_eval.send(provider)
|
25
|
+
elsif provider.respond_to?(:items)
|
26
|
+
provider.items
|
27
|
+
elsif provider.respond_to?(:each)
|
28
|
+
provider
|
29
|
+
else
|
30
|
+
raise "items_provider either must be a symbol specifying the helper-method to call, an object with an items-method defined or an enumerable representing the items"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|