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,144 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def explicit_navigation_args
|
6
|
+
self.adapter.controller.instance_variable_get(:"@sn_current_navigation_args")
|
7
|
+
end
|
8
|
+
|
9
|
+
# Reads the current navigation for the specified level from the controller.
|
10
|
+
# Returns nil if there is no current navigation set for level.
|
11
|
+
def current_navigation_for(level)
|
12
|
+
self.adapter.controller.instance_variable_get(:"@sn_current_navigation_#{level}")
|
13
|
+
end
|
14
|
+
|
15
|
+
# If any navigation has been explicitely set in the controller this method evaluates the specified args set in the controller and sets
|
16
|
+
# the correct instance variable in the controller.
|
17
|
+
def handle_explicit_navigation
|
18
|
+
if SimpleNavigation.explicit_navigation_args
|
19
|
+
level, navigation = parse_explicit_navigation_args
|
20
|
+
self.adapter.controller.instance_variable_set(:"@sn_current_navigation_#{level}", navigation)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO: refactor this ugly thing to make it nice and short
|
25
|
+
def parse_explicit_navigation_args
|
26
|
+
args = SimpleNavigation.explicit_navigation_args
|
27
|
+
args = [Hash.new] if args.empty?
|
28
|
+
if args.first.kind_of? Hash
|
29
|
+
options = args.first
|
30
|
+
else # args is a list of current navigation for several levels
|
31
|
+
options = {}
|
32
|
+
if args.size == 1 #only one navi-key has been specified, try to find out level
|
33
|
+
level = SimpleNavigation.primary_navigation.level_for_item(args.first)
|
34
|
+
options[:"level_#{level}"] = args.first if level
|
35
|
+
else
|
36
|
+
args.each_with_index {|arg, i| options[:"level_#{i + 1}"] = arg}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
#only the deepest level is relevant
|
40
|
+
level = options.inject(0) do |max, kv|
|
41
|
+
kv.first.to_s =~ /level_(\d)/
|
42
|
+
max = $1.to_i if $1.to_i > max
|
43
|
+
max
|
44
|
+
end
|
45
|
+
raise ArgumentError, "Invalid level specified or item key not found" if level == 0
|
46
|
+
[level, options[:"level_#{level}"]]
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# Adds methods for explicitely setting the current 'active' navigation to the controllers.
|
52
|
+
# Since version 2.0.0 the simple_navigation plugin determines the active navigation based on the current url by default (auto highlighting),
|
53
|
+
# so explicitely defining the active navigation in the controllers is only needed for edge cases where automatic highlighting does not work.
|
54
|
+
#
|
55
|
+
# On the controller class level, use the <tt>navigation</tt> method to set the active navigation for all actions in the controller.
|
56
|
+
# Let's assume that we have a primary navigation item :account which in turn has a sub navigation item :settings.
|
57
|
+
#
|
58
|
+
# ==== Examples
|
59
|
+
# class AccountController << ActionController
|
60
|
+
# navigation :account
|
61
|
+
# ...
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# class AccountSettingsController << ActionController
|
65
|
+
# navigation :settings
|
66
|
+
# ...
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# The first example sets the current primary navigation to :account for all actions. No active sub_navigation.
|
70
|
+
# The second example sets the current sub navigation to :settings and since it is a child of :account the current primary navigation is set to :account.
|
71
|
+
#
|
72
|
+
# On the controller instance level, use the <tt>current_navigation</tt> method to define the active navigation for a specific action.
|
73
|
+
# The navigation item that is set in <tt>current_navigation</tt> overrides the one defined on the controller class level (see <tt>navigation</tt> method).
|
74
|
+
# Thus if you have an :account primary item with a :special sub navigation item:
|
75
|
+
#
|
76
|
+
# ==== Example
|
77
|
+
# class AccountController << ActionController
|
78
|
+
# navigation :account
|
79
|
+
#
|
80
|
+
# def your_special_action
|
81
|
+
# ...
|
82
|
+
# current_navigation :special
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# The code above still sets the active primary navigation to :account for all actions, but sets the sub_navigation to :account -> :special for 'your_special_action'.
|
87
|
+
#
|
88
|
+
# Note 1: As you can see above you just have to set the navigation item of your 'deepest' navigation level as active and all its parents are marked as active, too.
|
89
|
+
#
|
90
|
+
# Note 2: The specified symbols must match the keys for your navigation items in your config/navigation.rb file.
|
91
|
+
module ControllerMethods
|
92
|
+
def self.included(base) #:nodoc:
|
93
|
+
base.class_eval do
|
94
|
+
extend ClassMethods
|
95
|
+
include InstanceMethods
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
module ClassMethods
|
100
|
+
# Sets the active navigation for all actions in this controller.
|
101
|
+
#
|
102
|
+
# The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
|
103
|
+
def navigation(*args)
|
104
|
+
self.class_eval do
|
105
|
+
define_method :sn_set_navigation do
|
106
|
+
current_navigation(*args)
|
107
|
+
end
|
108
|
+
protected :sn_set_navigation
|
109
|
+
before_filter :sn_set_navigation
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module InstanceMethods
|
115
|
+
# Sets the active navigation. Call this method in any action to override the controller-wide active navigation
|
116
|
+
# specified by navigation.
|
117
|
+
#
|
118
|
+
# The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
|
119
|
+
def current_navigation(*args)
|
120
|
+
@sn_current_navigation_args = args
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
class Item
|
127
|
+
|
128
|
+
def selected_by_config?
|
129
|
+
key == SimpleNavigation.current_navigation_for(@container.level)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
class ItemContainer
|
135
|
+
|
136
|
+
def selected_item
|
137
|
+
self[SimpleNavigation.current_navigation_for(self.level)] || items.find {|i| i.selected?}
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
ActionController::Base.send(:include, SimpleNavigation::ControllerMethods)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'simple_navigation/rendering/helpers'
|
2
|
+
require 'simple_navigation/rendering/renderer/base'
|
3
|
+
|
4
|
+
module SimpleNavigation
|
5
|
+
module Renderer
|
6
|
+
autoload :List, 'simple_navigation/rendering/renderer/list'
|
7
|
+
autoload :Links, 'simple_navigation/rendering/renderer/links'
|
8
|
+
autoload :Breadcrumbs, 'simple_navigation/rendering/renderer/breadcrumbs'
|
9
|
+
autoload :Text, 'simple_navigation/rendering/renderer/text'
|
10
|
+
autoload :Json, 'simple_navigation/rendering/renderer/json'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
|
3
|
+
# View helpers to render the navigation.
|
4
|
+
#
|
5
|
+
# Use render_navigation as following to render your navigation:
|
6
|
+
# * call <tt>render_navigation</tt> without :level option to render your complete navigation as nested tree.
|
7
|
+
# * call <tt>render_navigation(:level => x)</tt> to render a specific navigation level (e.g. :level => 1 to render your primary navigation, :level => 2 to render the sub navigation and so forth)
|
8
|
+
# * call <tt>render_navigation(:level => 2..3)</tt> to render navigation levels 2 and 3).
|
9
|
+
# For example, you could use render_navigation(:level => 1) to render your primary navigation as tabs and render_navigation(:level => 2..3) to render the rest of the navigation as a tree in a sidebar.
|
10
|
+
#
|
11
|
+
# ==== Examples (using Haml)
|
12
|
+
# #primary_navigation= render_navigation(:level => 1)
|
13
|
+
#
|
14
|
+
# #sub_navigation= render_navigation(:level => 2)
|
15
|
+
#
|
16
|
+
# #nested_navigation= render_navigation
|
17
|
+
#
|
18
|
+
# #top_navigation= render_navigation(:level => 1..2)
|
19
|
+
# #sidebar_navigation= render_navigation(:level => 3)
|
20
|
+
module Helpers
|
21
|
+
|
22
|
+
# Renders the navigation according to the specified options-hash.
|
23
|
+
#
|
24
|
+
# The following options are supported:
|
25
|
+
# * <tt>:level</tt> - defaults to :all which renders the the sub_navigation for an active primary_navigation inside that active primary_navigation item.
|
26
|
+
# Specify a specific level to only render that level of navigation (e.g. :level => 1 for primary_navigation etc...).
|
27
|
+
# Specifiy a Range of levels to render only those specific levels (e.g. :level => 1..2 to render both your first and second levels, maybe you want to render your third level somewhere else on the page)
|
28
|
+
# * <tt>:expand_all</tt> - defaults to false. If set to true the all specified levels will be rendered as a fully expanded tree (always open). This is useful for javascript menus like Superfish.
|
29
|
+
# * <tt>:context</tt> - specifies the context for which you would render the navigation. Defaults to :default which loads the default navigation.rb (i.e. config/navigation.rb).
|
30
|
+
# If you specify a context then the plugin tries to load the configuration file for that context, e.g. if you call <tt>render_navigation(:context => :admin)</tt> the file config/admin_navigation.rb
|
31
|
+
# will be loaded and used for rendering the navigation.
|
32
|
+
# * <tt>:items</tt> - you can specify the items directly (e.g. if items are dynamically generated from database). See SimpleNavigation::ItemsProvider for documentation on what to provide as items.
|
33
|
+
# * <tt>:renderer</tt> - specify the renderer to be used for rendering the navigation. Either provide the Class or a symbol matching a registered renderer. Defaults to :list (html list renderer).
|
34
|
+
#
|
35
|
+
# Instead of using the <tt>:items</tt> option, a block can be passed to specify the items dynamically
|
36
|
+
#
|
37
|
+
# render_navigation do |menu|
|
38
|
+
# menu.item :posts, "Posts", posts_path
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
def render_navigation(options={},&block)
|
42
|
+
container = active_navigation_item_container(options,&block)
|
43
|
+
container && container.render(options)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the name of the currently active navigation item belonging to the specified level.
|
47
|
+
#
|
48
|
+
# See Helpers#active_navigation_item for supported options.
|
49
|
+
#
|
50
|
+
# Returns an empty string if no active item can be found for the specified options
|
51
|
+
def active_navigation_item_name(options={})
|
52
|
+
active_navigation_item(options,'') { |item| item.name(:apply_generator => false) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the key of the currently active navigation item belonging to the specified level.
|
56
|
+
#
|
57
|
+
# See Helpers#active_navigation_item for supported options.
|
58
|
+
#
|
59
|
+
# Returns <tt>nil</tt> if no active item can be found for the specified options
|
60
|
+
def active_navigation_item_key(options={})
|
61
|
+
active_navigation_item(options) { |item| item.key }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the currently active navigation item belonging to the specified level.
|
65
|
+
#
|
66
|
+
# The following options are supported:
|
67
|
+
# * <tt>:level</tt> - defaults to :all which returns the most specific/deepest selected item (the leaf).
|
68
|
+
# Specify a specific level to only look for the selected item in the specified level of navigation (e.g. :level => 1 for primary_navigation etc...).
|
69
|
+
# * <tt>:context</tt> - specifies the context for which you would like to find the active navigation item. Defaults to :default which loads the default navigation.rb (i.e. config/navigation.rb).
|
70
|
+
# If you specify a context then the plugin tries to load the configuration file for that context, e.g. if you call <tt>active_navigation_item_name(:context => :admin)</tt> the file config/admin_navigation.rb
|
71
|
+
# will be loaded and used for searching the active item.
|
72
|
+
# * <tt>:items</tt> - you can specify the items directly (e.g. if items are dynamically generated from database). See SimpleNavigation::ItemsProvider for documentation on what to provide as items.
|
73
|
+
#
|
74
|
+
# Returns the supplied <tt>value_for_nil</tt> object (<tt>nil</tt>
|
75
|
+
# by default) if no active item can be found for the specified
|
76
|
+
# options
|
77
|
+
def active_navigation_item(options={},value_for_nil = nil)
|
78
|
+
options[:level] = :leaves if options[:level].nil? || options[:level] == :all
|
79
|
+
container = active_navigation_item_container(options)
|
80
|
+
if container && (item = container.selected_item)
|
81
|
+
block_given? ? yield(item) : item
|
82
|
+
else
|
83
|
+
value_for_nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns the currently active item container belonging to the specified level.
|
88
|
+
#
|
89
|
+
# The following options are supported:
|
90
|
+
# * <tt>:level</tt> - defaults to :all which returns the least specific/shallowest selected item.
|
91
|
+
# Specify a specific level to only look for the selected item in the specified level of navigation (e.g. :level => 1 for primary_navigation etc...).
|
92
|
+
# * <tt>:context</tt> - specifies the context for which you would like to find the active navigation item. Defaults to :default which loads the default navigation.rb (i.e. config/navigation.rb).
|
93
|
+
# If you specify a context then the plugin tries to load the configuration file for that context, e.g. if you call <tt>active_navigation_item_name(:context => :admin)</tt> the file config/admin_navigation.rb
|
94
|
+
# will be loaded and used for searching the active item.
|
95
|
+
# * <tt>:items</tt> - you can specify the items directly (e.g. if items are dynamically generated from database). See SimpleNavigation::ItemsProvider for documentation on what to provide as items.
|
96
|
+
#
|
97
|
+
# Returns <tt>nil</tt> if no active item container can be found
|
98
|
+
def active_navigation_item_container(options={},&block)
|
99
|
+
options = SimpleNavigation::Helpers::apply_defaults(options)
|
100
|
+
SimpleNavigation::Helpers::load_config(options,self,&block)
|
101
|
+
container = SimpleNavigation.active_item_container_for(options[:level])
|
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
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module SimpleNavigation
|
4
|
+
module Renderer
|
5
|
+
|
6
|
+
# This is the base class for all renderers.
|
7
|
+
#
|
8
|
+
# A renderer is responsible for rendering an ItemContainer and its containing items to HTML.
|
9
|
+
class Base
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
attr_reader :options, :adapter
|
13
|
+
|
14
|
+
def_delegators :adapter, :link_to, :content_tag
|
15
|
+
|
16
|
+
def initialize(options) #:nodoc:
|
17
|
+
@options = options
|
18
|
+
@adapter = SimpleNavigation.adapter
|
19
|
+
end
|
20
|
+
|
21
|
+
def expand_all?
|
22
|
+
!!options[:expand_all]
|
23
|
+
end
|
24
|
+
|
25
|
+
def level
|
26
|
+
options[:level] || :all
|
27
|
+
end
|
28
|
+
|
29
|
+
def skip_if_empty?
|
30
|
+
!!options[:skip_if_empty]
|
31
|
+
end
|
32
|
+
|
33
|
+
def include_sub_navigation?(item)
|
34
|
+
consider_sub_navigation?(item) && expand_sub_navigation?(item)
|
35
|
+
end
|
36
|
+
|
37
|
+
def render_sub_navigation_for(item)
|
38
|
+
item.sub_navigation.render(self.options)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Renders the specified ItemContainer to HTML.
|
42
|
+
#
|
43
|
+
# When implementing a renderer, please consider to call include_sub_navigation? to determin
|
44
|
+
# whether an item's sub_navigation should be rendered or not.
|
45
|
+
#
|
46
|
+
def render(item_container)
|
47
|
+
raise 'subclass responsibility'
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def consider_sub_navigation?(item)
|
53
|
+
return false if item.sub_navigation.nil?
|
54
|
+
case level
|
55
|
+
when :all
|
56
|
+
return true
|
57
|
+
when Integer
|
58
|
+
return false
|
59
|
+
when Range
|
60
|
+
return item.sub_navigation.level <= level.max
|
61
|
+
end
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
def expand_sub_navigation?(item)
|
66
|
+
expand_all? || item.selected?
|
67
|
+
end
|
68
|
+
|
69
|
+
# to allow overriding when there is specific logic determining
|
70
|
+
# when a link should not be rendered (eg. breadcrumbs renderer
|
71
|
+
# does not render the final breadcrumb as a link when instructed
|
72
|
+
# not to do so.)
|
73
|
+
def suppress_link?(item)
|
74
|
+
item.url.nil?
|
75
|
+
end
|
76
|
+
|
77
|
+
# determine and return link or static content depending on
|
78
|
+
# item/renderer conditions.
|
79
|
+
def tag_for(item)
|
80
|
+
if suppress_link?(item)
|
81
|
+
content_tag('span', item.name, link_options_for(item).except(:method))
|
82
|
+
else
|
83
|
+
link_to("<div class=\"menubg\"></div><i class=\"icon-#{item.name.downcase}\"></i><span>" + item.name + '</span>', item.url, options_for(item))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# to allow overriding when link options should be special-cased
|
88
|
+
# (eg. links renderer uses item options for the a-tag rather
|
89
|
+
# than an li-tag).
|
90
|
+
def options_for(item)
|
91
|
+
link_options_for(item)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Extracts the options relevant for the generated link
|
95
|
+
#
|
96
|
+
def link_options_for(item)
|
97
|
+
special_options = {:method => item.method, :class => item.selected_class}.reject {|k, v| v.nil? }
|
98
|
+
link_options = item.html_options[:link]
|
99
|
+
return special_options unless link_options
|
100
|
+
opts = special_options.merge(link_options)
|
101
|
+
opts[:class] = [link_options[:class], item.selected_class].flatten.compact.join(' ')
|
102
|
+
opts.delete(:class) if opts[:class].nil? || opts[:class] == ''
|
103
|
+
opts
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
module Renderer
|
3
|
+
|
4
|
+
# Renders an ItemContainer as a <div> element and its containing items as <a> elements.
|
5
|
+
# It only renders 'selected' elements.
|
6
|
+
#
|
7
|
+
# By default, the renderer sets the item's key as dom_id for the rendered <a> element unless the config option <tt>autogenerate_item_ids</tt> is set to false.
|
8
|
+
# The id can also be explicitely specified by setting the id in the html-options of the 'item' method in the config/navigation.rb file.
|
9
|
+
# The ItemContainer's dom_class and dom_id are applied to the surrounding <div> element.
|
10
|
+
#
|
11
|
+
class Breadcrumbs < SimpleNavigation::Renderer::Base
|
12
|
+
|
13
|
+
def render(item_container)
|
14
|
+
content = a_tags(item_container).join(join_with)
|
15
|
+
content_tag(:div,
|
16
|
+
prefix_for(content) + content,
|
17
|
+
{:id => item_container.dom_id, :class => item_container.dom_class})
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def a_tags(item_container)
|
23
|
+
item_container.items.inject([]) do |list, item|
|
24
|
+
if item.selected?
|
25
|
+
list << tag_for(item)
|
26
|
+
if include_sub_navigation?(item)
|
27
|
+
list.concat a_tags(item.sub_navigation)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
list
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def join_with
|
35
|
+
@join_with ||= options[:join_with] || " "
|
36
|
+
end
|
37
|
+
|
38
|
+
def suppress_link?(item)
|
39
|
+
super || (options[:static_leaf] && item.active_leaf_class)
|
40
|
+
end
|
41
|
+
|
42
|
+
def prefix_for(content)
|
43
|
+
content.empty? ? '' : options[:prefix] || ''
|
44
|
+
end
|
45
|
+
|
46
|
+
# Extracts the options relevant for the generated link
|
47
|
+
#
|
48
|
+
def link_options_for(item)
|
49
|
+
if options[:allow_classes_and_ids]
|
50
|
+
opts = super
|
51
|
+
opts[:id] = "breadcrumb_#{opts[:id]}" if opts[:id]
|
52
|
+
opts
|
53
|
+
else
|
54
|
+
{:method => item.method}.merge(item.html_options.except(:class,:id))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|