simple-navigation 1.4.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/CHANGELOG +8 -0
- data/README +5 -1
- data/Rakefile +14 -4
- data/VERSION.yml +3 -3
- data/generators/navigation_config/templates/config/navigation.rb +9 -2
- data/lib/simple_navigation/configuration.rb +14 -8
- data/lib/simple_navigation/controller_methods.rb +24 -20
- data/lib/simple_navigation/helpers.rb +49 -34
- data/lib/simple_navigation/item.rb +56 -15
- data/lib/simple_navigation/item_container.rb +60 -10
- data/lib/simple_navigation/renderer/base.rb +8 -8
- data/lib/simple_navigation/renderer/list.rb +11 -10
- data/lib/simple_navigation.rb +68 -6
- data/simple-navigation.gemspec +4 -4
- data/spec/lib/simple_navigation/configuration_spec.rb +61 -0
- data/spec/lib/simple_navigation/controller_methods_spec.rb +9 -13
- data/spec/lib/simple_navigation/helpers_spec.rb +38 -38
- data/spec/lib/simple_navigation/item_container_spec.rb +146 -5
- data/spec/lib/simple_navigation/item_spec.rb +229 -34
- data/spec/lib/simple_navigation/renderer/base_spec.rb +7 -3
- data/spec/lib/simple_navigation/renderer/list_spec.rb +31 -15
- data/spec/lib/simple_navigation_spec.rb +83 -0
- metadata +4 -4
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
*2.0.0
|
2
|
+
|
3
|
+
* added auto_highlight feature. Active navigation is determined by comparing urls, no need to explicitly set it in the controllers anymore. Thanks to Jack Dempsey and Florian Hanke for the support on this.
|
4
|
+
* added ability to create multi-level navigations (not just limited to primary and secondary navigation). Thanks again to Jack Dempsey for the motivation ;-)
|
5
|
+
* simplified the process to explicitly set the navigation in the controller (where needed) - only deepest level has to be specified
|
6
|
+
* made auto_highlight feature configurable both on global and item_container's level
|
7
|
+
* config file is now evaluated in template if ever possible (not in controller anymore)
|
8
|
+
|
1
9
|
*1.4.2
|
2
10
|
|
3
11
|
* explicitly loading all source files when requiring 'simple_navigation'.
|
data/README
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
|
2
2
|
== Simple Navigation
|
3
3
|
|
4
|
-
Simple Navigation is a
|
4
|
+
Simple Navigation is a ruby library for creating navigations (with multiple levels) for your Ruby on Rails application.
|
5
|
+
If you upgrade to version 2.x.x please recheck the updated documentation on http://wiki.github.com/andi/simple-navigation.
|
5
6
|
|
6
7
|
Source code:
|
7
8
|
git://github.com/andi/simple-navigation.git
|
@@ -9,6 +10,9 @@ Source code:
|
|
9
10
|
Documentation:
|
10
11
|
http://wiki.github.com/andi/simple-navigation
|
11
12
|
|
13
|
+
RDoc:
|
14
|
+
http://andi.rubyforge.org
|
15
|
+
|
12
16
|
Online Demo:
|
13
17
|
http://simple-navigation-demo.andischacke.com
|
14
18
|
|
data/Rakefile
CHANGED
@@ -11,6 +11,16 @@ Spec::Rake::SpecTask.new(:spec) do |t|
|
|
11
11
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
12
12
|
end
|
13
13
|
|
14
|
+
namespace :spec do
|
15
|
+
desc "Run all specs with RCov"
|
16
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
17
|
+
t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
|
18
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
19
|
+
t.rcov = true
|
20
|
+
t.rcov_opts = ['--exclude', 'spec,/Users/']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
14
24
|
desc 'Generate documentation for the simple_navigation plugin.'
|
15
25
|
Rake::RDocTask.new(:rdoc) do |rdoc|
|
16
26
|
rdoc.rdoc_dir = 'rdoc'
|
@@ -24,10 +34,10 @@ begin
|
|
24
34
|
require 'jeweler'
|
25
35
|
Jeweler::Tasks.new do |gemspec|
|
26
36
|
gemspec.name = "simple-navigation"
|
27
|
-
gemspec.summary = "Simple Navigation is a ruby library for creating
|
37
|
+
gemspec.summary = "Simple Navigation is a ruby library for creating navigations (with multiple levels) for your Ruby on Rails application."
|
28
38
|
gemspec.email = "andreas.schacke@gmail.com"
|
29
39
|
gemspec.homepage = "http://github.com/andi/simple-navigation"
|
30
|
-
gemspec.description = "
|
40
|
+
gemspec.description = "With the simple-navigation gem installed you can easily create multilevel navigations for your Ruby on Rails applications. The navigation is defined in a single configuration file. It supports automatic as well as explicit highlighting of the currently active navigation."
|
31
41
|
gemspec.authors = ["Andi Schacke"]
|
32
42
|
gemspec.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
33
43
|
gemspec.files += ["CHANGELOG"]
|
@@ -36,6 +46,6 @@ begin
|
|
36
46
|
Jeweler::RubyforgeTasks.new do |rubyforge|
|
37
47
|
rubyforge.doc_task = "rdoc"
|
38
48
|
end
|
39
|
-
rescue LoadError
|
40
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
49
|
+
rescue LoadError => e
|
50
|
+
puts "Jeweler not available (#{e}). Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
41
51
|
end
|
data/VERSION.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
---
|
2
|
-
:patch:
|
3
|
-
:major:
|
4
|
-
:minor:
|
2
|
+
:patch: 0
|
3
|
+
:major: 2
|
4
|
+
:minor: 0
|
@@ -12,10 +12,14 @@ SimpleNavigation::Configuration.run do |navigation|
|
|
12
12
|
# driven hovering menus like the jquery superfish plugin
|
13
13
|
# navigation.render_all_levels = true
|
14
14
|
|
15
|
-
# Item keys are normally added to list items.
|
16
|
-
#
|
15
|
+
# Item keys are normally added to list items as id.
|
16
|
+
# This setting turns that off
|
17
17
|
# navigation.autogenerate_item_ids = false
|
18
18
|
|
19
|
+
# The auto highlight feature is turned on by default.
|
20
|
+
# This turns it off globally (for the whole plugin)
|
21
|
+
# navigation.auto_highlight = false
|
22
|
+
|
19
23
|
# Define the primary navigation
|
20
24
|
navigation.items do |primary|
|
21
25
|
# Add an item to the primary navigation. The following params apply:
|
@@ -42,6 +46,9 @@ SimpleNavigation::Configuration.run do |navigation|
|
|
42
46
|
# works for all levels of the menu
|
43
47
|
# primary.dom_id = 'menu-id'
|
44
48
|
# primary.dom_class = 'menu-class'
|
49
|
+
|
50
|
+
# You can turn off auto highlighting for a specific level
|
51
|
+
# primary.auto_highlight = false
|
45
52
|
|
46
53
|
end
|
47
54
|
|
@@ -6,25 +6,30 @@ module SimpleNavigation
|
|
6
6
|
class Configuration
|
7
7
|
include Singleton
|
8
8
|
|
9
|
-
attr_accessor :renderer
|
10
|
-
attr_accessor :selected_class
|
11
|
-
attr_accessor :render_all_levels
|
12
|
-
attr_accessor :autogenerate_item_ids
|
9
|
+
attr_accessor :renderer, :selected_class, :render_all_levels, :autogenerate_item_ids, :auto_highlight
|
13
10
|
attr_reader :primary_navigation
|
14
11
|
|
15
12
|
class << self
|
16
13
|
|
17
14
|
# Evals the config_file for the given navigation_context inside the specified context (usually a controller or view)
|
18
15
|
def eval_config(context, navigation_context = :default)
|
19
|
-
context.instance_eval(SimpleNavigation.config_files[navigation_context])
|
20
16
|
SimpleNavigation.controller = extract_controller_from context
|
17
|
+
SimpleNavigation.template = SimpleNavigation.controller.instance_variable_get(:@template)
|
18
|
+
context_for_eval.instance_eval(SimpleNavigation.config_files[navigation_context])
|
21
19
|
end
|
22
|
-
|
20
|
+
|
23
21
|
# Starts processing the configuration
|
24
22
|
def run(&block)
|
25
23
|
block.call Configuration.instance
|
26
24
|
end
|
27
25
|
|
26
|
+
# Returns the context in which the config file should be evaluated.
|
27
|
+
# This is preferably the template, otherwise te controller
|
28
|
+
def context_for_eval
|
29
|
+
raise 'no context set for evaluation the config file' unless SimpleNavigation.template || SimpleNavigation.controller
|
30
|
+
SimpleNavigation.template || SimpleNavigation.controller
|
31
|
+
end
|
32
|
+
|
28
33
|
# Extracts a controller from the context.
|
29
34
|
def extract_controller_from(context)
|
30
35
|
if context.respond_to? :controller
|
@@ -33,8 +38,8 @@ module SimpleNavigation
|
|
33
38
|
context
|
34
39
|
end
|
35
40
|
end
|
36
|
-
|
37
|
-
end
|
41
|
+
|
42
|
+
end #class << self
|
38
43
|
|
39
44
|
# Sets the config's default-settings
|
40
45
|
def initialize
|
@@ -42,6 +47,7 @@ module SimpleNavigation
|
|
42
47
|
@selected_class = 'selected'
|
43
48
|
@render_all_levels = false
|
44
49
|
@autogenerate_item_ids = true
|
50
|
+
@auto_highlight = true
|
45
51
|
end
|
46
52
|
|
47
53
|
# Yields an SimpleNavigation::ItemContainer for adding navigation items
|
@@ -1,9 +1,12 @@
|
|
1
1
|
#TODO: add :except and :only options to navigation method
|
2
2
|
module SimpleNavigation
|
3
3
|
|
4
|
-
# Adds methods for
|
4
|
+
# Adds methods for explicitely setting the current 'active' navigation to the controllers.
|
5
|
+
# Since version 2.0.0 the simple_navigation plugin determines the active navigation based on the current url by default (auto highlighting),
|
6
|
+
# so explicitely defining the active navigation in the controllers is only needed for edge cases where automatic highlighting does not work.
|
5
7
|
#
|
6
|
-
# On the controller class level, use the navigation method to set the active navigation for all actions in the controller.
|
8
|
+
# On the controller class level, use the <tt>navigation</tt> method to set the active navigation for all actions in the controller.
|
9
|
+
# Let's assume that we have a primary navigation item :account which in turn has a sub navigation item :settings.
|
7
10
|
#
|
8
11
|
# ==== Examples
|
9
12
|
# class AccountController << ActionController
|
@@ -12,15 +15,16 @@ module SimpleNavigation
|
|
12
15
|
# end
|
13
16
|
#
|
14
17
|
# class AccountSettingsController << ActionController
|
15
|
-
# navigation :
|
18
|
+
# navigation :settings
|
16
19
|
# ...
|
17
20
|
# end
|
18
21
|
#
|
19
|
-
# The first example sets the
|
20
|
-
# The second example sets the
|
22
|
+
# The first example sets the current primary navigation to :account for all actions. No active sub_navigation.
|
23
|
+
# 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.
|
21
24
|
#
|
22
|
-
# On the controller instance level, use the current_navigation method to define the active navigation for a specific action.
|
23
|
-
# The navigation item that is set in current_navigation overrides the one defined on the controller class level (see navigation method).
|
25
|
+
# On the controller instance level, use the <tt>current_navigation</tt> method to define the active navigation for a specific action.
|
26
|
+
# 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).
|
27
|
+
# Thus if you have an :account primary item with a :special sub navigation item:
|
24
28
|
#
|
25
29
|
# ==== Example
|
26
30
|
# class AccountController << ActionController
|
@@ -28,13 +32,15 @@ module SimpleNavigation
|
|
28
32
|
#
|
29
33
|
# def your_special_action
|
30
34
|
# ...
|
31
|
-
# current_navigation :
|
35
|
+
# current_navigation :special
|
32
36
|
# end
|
33
37
|
# end
|
34
38
|
#
|
35
|
-
# The code above still sets the active primary navigation to :account but
|
39
|
+
# 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'.
|
36
40
|
#
|
37
|
-
# Note:
|
41
|
+
# 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.
|
42
|
+
#
|
43
|
+
# Note 2: The specified symbols must match the keys for your navigation items in your config/navigation.rb file.
|
38
44
|
module ControllerMethods
|
39
45
|
def self.included(base) #:nodoc:
|
40
46
|
base.class_eval do
|
@@ -48,26 +54,24 @@ module SimpleNavigation
|
|
48
54
|
module ClassMethods
|
49
55
|
# Sets the active navigation for all actions in this controller.
|
50
56
|
#
|
51
|
-
# The specified
|
52
|
-
def navigation(
|
57
|
+
# The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
|
58
|
+
def navigation(*args)
|
53
59
|
self.class_eval do
|
54
|
-
define_method :
|
55
|
-
current_navigation(
|
60
|
+
define_method :sn_set_navigation do
|
61
|
+
current_navigation(*args)
|
56
62
|
end
|
57
|
-
before_filter :
|
63
|
+
before_filter :sn_set_navigation
|
58
64
|
end
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
68
|
module InstanceMethods
|
63
|
-
|
64
69
|
# Sets the active navigation. Call this method in any action to override the controller-wide active navigation
|
65
70
|
# specified by navigation.
|
66
71
|
#
|
67
|
-
# The specified
|
68
|
-
def current_navigation(
|
69
|
-
@
|
70
|
-
@current_secondary_navigation = sub_navigation
|
72
|
+
# The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
|
73
|
+
def current_navigation(*args)
|
74
|
+
@sn_current_navigation_args = args
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
@@ -2,63 +2,78 @@ module SimpleNavigation
|
|
2
2
|
|
3
3
|
# View helpers to render the navigation.
|
4
4
|
#
|
5
|
-
# Use
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Use render_navigation as following to render your navigation:
|
6
|
+
# * call <tt>render_navigation</tt> without :level option to render your 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
8
|
#
|
9
9
|
# ==== Examples (using Haml)
|
10
|
-
# #primary_navigation=
|
10
|
+
# #primary_navigation= render_navigation(:level => 1)
|
11
11
|
#
|
12
|
-
# #sub_navigation=
|
12
|
+
# #sub_navigation= render_navigation(:level => 2)
|
13
13
|
#
|
14
|
-
# #
|
14
|
+
# #nested_navigation= render_navigation
|
15
15
|
#
|
16
|
+
# Please note that <tt>render_primary_navigation</tt> and <tt>render_sub_navigation</tt> still work, but have been deprecated and may be removed in a future release.
|
16
17
|
module Helpers
|
17
18
|
|
18
19
|
# Renders the navigation according to the specified options-hash.
|
19
20
|
#
|
20
21
|
# The following options are supported:
|
21
|
-
# * <tt
|
22
|
-
#
|
23
|
-
# * <tt
|
24
|
-
#
|
22
|
+
# * <tt>:level</tt> - defaults to :nested which renders the the sub_navigation for an active primary_navigation inside that active primary_navigation item.
|
23
|
+
# Specify a specific level to only render that level of navigation (e.g. :level => 1 for primary_navigation etc...).
|
24
|
+
# * <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).
|
25
|
+
# 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
|
25
26
|
# will be loaded and used for rendering the navigation.
|
26
27
|
#
|
27
28
|
def render_navigation(*args)
|
28
29
|
args = [Hash.new] if args.empty?
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
SimpleNavigation.load_config(navigation_context)
|
40
|
-
SimpleNavigation::Configuration.eval_config(self, navigation_context)
|
41
|
-
case level
|
42
|
-
when :primary
|
43
|
-
SimpleNavigation.primary_navigation.render(@current_primary_navigation)
|
44
|
-
when :secondary
|
45
|
-
primary = SimpleNavigation.primary_navigation[@current_primary_navigation]
|
46
|
-
primary.sub_navigation.render(@current_secondary_navigation) if primary && primary.sub_navigation
|
30
|
+
options = extract_backwards_compatible_options(*args)
|
31
|
+
options = {:context => :default, :level => :nested}.merge(options)
|
32
|
+
SimpleNavigation.load_config(options[:context])
|
33
|
+
SimpleNavigation::Configuration.eval_config(self, options[:context])
|
34
|
+
SimpleNavigation.handle_explicit_navigation
|
35
|
+
case options[:level]
|
36
|
+
when Integer
|
37
|
+
active_item_container = SimpleNavigation.active_item_container_for(options[:level])
|
38
|
+
active_item_container.render if active_item_container
|
47
39
|
when :nested
|
48
|
-
SimpleNavigation.primary_navigation.render(
|
40
|
+
SimpleNavigation.primary_navigation.render(true)
|
49
41
|
else
|
50
|
-
raise ArgumentError, "Invalid navigation level: #{level}"
|
42
|
+
raise ArgumentError, "Invalid navigation level: #{options[:level]}"
|
51
43
|
end
|
52
44
|
end
|
53
45
|
|
54
|
-
# Renders the primary_navigation with the configured renderer. Calling render_navigation(:level =>
|
46
|
+
# Deprecated. Renders the primary_navigation with the configured renderer. Calling render_navigation(:level => 0) has the same effect.
|
55
47
|
def render_primary_navigation(options = {})
|
56
|
-
|
48
|
+
ActiveSupport::Deprecation.warn("SimpleNavigation::Helpers.render_primary_navigation has been deprected. Please use render_navigation(:level => 1) instead")
|
49
|
+
render_navigation(options.merge(:level => 1))
|
57
50
|
end
|
58
51
|
|
59
|
-
# Renders the sub_navigation with the configured renderer. Calling render_navigation(:level =>
|
52
|
+
# Deprecated. Renders the sub_navigation with the configured renderer. Calling render_navigation(:level => 1) has the same effect.
|
60
53
|
def render_sub_navigation(options = {})
|
61
|
-
|
54
|
+
ActiveSupport::Deprecation.warn("SimpleNavigation::Helpers.render_primary_navigation has been deprected. Please use render_navigation(:level => 2) instead")
|
55
|
+
render_navigation(options.merge(:level => 2))
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def extract_backwards_compatible_options(*args)
|
61
|
+
case args.first
|
62
|
+
when Hash
|
63
|
+
options = args.first
|
64
|
+
options[:level] = 1 if options[:level] == :primary
|
65
|
+
options[:level] = 2 if options[:level] == :secondary
|
66
|
+
when Symbol
|
67
|
+
raise ArgumentError, "Invalid arguments" unless [:primary, :secondary, :nested].include? args.first
|
68
|
+
options = Hash.new
|
69
|
+
options[:level] = args.first
|
70
|
+
options[:level] = 1 if options[:level] == :primary
|
71
|
+
options[:level] = 2 if options[:level] == :secondary
|
72
|
+
options.merge!(args[1] || {})
|
73
|
+
else
|
74
|
+
raise ArgumentError, "Invalid arguments"
|
75
|
+
end
|
76
|
+
options
|
62
77
|
end
|
63
78
|
|
64
79
|
end
|
@@ -6,43 +6,84 @@ module SimpleNavigation
|
|
6
6
|
attr_writer :html_options
|
7
7
|
|
8
8
|
# see ItemContainer#item
|
9
|
-
def initialize(key, name, url, options, sub_nav_block)
|
9
|
+
def initialize(container, key, name, url, options, sub_nav_block) #:nodoc:
|
10
|
+
@container = container
|
10
11
|
@key = key
|
11
12
|
@method = options.delete(:method)
|
12
13
|
@name = name
|
13
14
|
@url = url
|
14
15
|
@html_options = options
|
15
16
|
if sub_nav_block
|
16
|
-
@sub_navigation = ItemContainer.new
|
17
|
+
@sub_navigation = ItemContainer.new(@container.level + 1)
|
17
18
|
sub_nav_block.call @sub_navigation
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
# Returns true if this navigation item should be rendered as 'selected'
|
22
|
-
|
23
|
-
|
22
|
+
# Returns true if this navigation item should be rendered as 'selected'.
|
23
|
+
# An item is selected if
|
24
|
+
#
|
25
|
+
# * it has been explicitly selected in a controller or
|
26
|
+
# * it has a subnavigation and one of its subnavigation items is selected or
|
27
|
+
# * its url matches the url of the current request (auto highlighting)
|
28
|
+
#
|
29
|
+
def selected?
|
30
|
+
@selected = @selected || selected_by_config? || selected_by_subnav? || selected_by_url?
|
24
31
|
end
|
25
32
|
|
26
33
|
# Returns the html-options hash for the item, i.e. the options specified for this item in the config-file.
|
27
34
|
# It also adds the 'selected' class to the list of classes if necessary.
|
28
|
-
def html_options
|
35
|
+
def html_options
|
29
36
|
default_options = self.autogenerate_item_ids? ? {:id => key.to_s} : {}
|
30
37
|
options = default_options.merge(@html_options)
|
31
|
-
options[:class] = [@html_options[:class], self.selected_class
|
32
|
-
options.delete(:class) if options[:class].blank?
|
38
|
+
options[:class] = [@html_options[:class], self.selected_class].flatten.compact.join(' ')
|
39
|
+
options.delete(:class) if options[:class].blank?
|
33
40
|
options
|
34
41
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
42
|
+
|
43
|
+
# Returns the configured selected_class if the item is selected, nil otherwise
|
44
|
+
#
|
45
|
+
def selected_class
|
46
|
+
selected? ? SimpleNavigation.config.selected_class : nil
|
38
47
|
end
|
39
|
-
|
40
|
-
|
48
|
+
|
41
49
|
protected
|
42
|
-
|
50
|
+
|
51
|
+
# Returns true if item has a subnavigation and the sub_navigation is selected
|
52
|
+
def selected_by_subnav?
|
53
|
+
sub_navigation && sub_navigation.selected?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return true if item has explicitly selected in controllers
|
57
|
+
def selected_by_config?
|
58
|
+
key == @container.current_explicit_navigation
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns true if the item's url matches the request's current url.
|
62
|
+
def selected_by_url?
|
63
|
+
if auto_highlight?
|
64
|
+
!!(root_path_match? || (SimpleNavigation.template && SimpleNavigation.template.current_page?(url)))
|
65
|
+
else
|
66
|
+
false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns true if both the item's url and the request's url are root_path
|
71
|
+
def root_path_match?
|
72
|
+
url == '/' && SimpleNavigation.controller.request.path == '/'
|
73
|
+
end
|
74
|
+
|
75
|
+
# Converts url to url_hash. Accesses routing system, quite slow... Not used at the moment
|
76
|
+
# def hash_for_url(url) #:nodoc:
|
77
|
+
# ActionController::Routing::Routes.recognize_path(url, {:method => (method || :get)})
|
78
|
+
# end
|
79
|
+
|
43
80
|
def autogenerate_item_ids?
|
44
81
|
SimpleNavigation.config.autogenerate_item_ids
|
45
82
|
end
|
46
|
-
|
83
|
+
|
84
|
+
def auto_highlight?
|
85
|
+
SimpleNavigation.config.auto_highlight && @container.auto_highlight
|
86
|
+
end
|
87
|
+
|
47
88
|
end
|
48
89
|
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module SimpleNavigation
|
2
2
|
|
3
|
-
# Holds the Items for a navigation 'level'
|
3
|
+
# Holds the Items for a navigation 'level'.
|
4
4
|
class ItemContainer
|
5
5
|
|
6
|
-
attr_reader :items
|
7
|
-
attr_accessor :renderer, :dom_id, :dom_class
|
6
|
+
attr_reader :items, :level
|
7
|
+
attr_accessor :renderer, :dom_id, :dom_class, :auto_highlight
|
8
8
|
|
9
|
-
def initialize #:nodoc:
|
9
|
+
def initialize(level=1) #:nodoc:
|
10
|
+
@level = level
|
10
11
|
@items = []
|
11
|
-
@renderer =
|
12
|
+
@renderer = SimpleNavigation.config.renderer
|
13
|
+
@auto_highlight = true
|
12
14
|
end
|
13
15
|
|
14
16
|
# Creates a new navigation item.
|
@@ -30,23 +32,72 @@ module SimpleNavigation
|
|
30
32
|
#
|
31
33
|
# The <tt>block</tt> - if specified - will hold the item's sub_navigation.
|
32
34
|
def item(key, name, url, options={}, &block)
|
33
|
-
(@items << Item.new(key, name, url, options, block)) if should_add_item?(options)
|
35
|
+
(@items << SimpleNavigation::Item.new(self, key, name, url, options, block)) if should_add_item?(options)
|
34
36
|
end
|
35
37
|
|
36
38
|
# Returns the Item with the specified key, nil otherwise.
|
39
|
+
#
|
37
40
|
def [](navi_key)
|
38
41
|
items.find {|i| i.key == navi_key}
|
39
42
|
end
|
43
|
+
|
44
|
+
# Returns the level of the item specified by navi_key.
|
45
|
+
# Recursively works its way down the item's sub_navigations if the desired item is not found directly in this container's items.
|
46
|
+
# Returns nil item cannot be found.
|
47
|
+
#
|
48
|
+
def level_for_item(navi_key)
|
49
|
+
my_item = self[navi_key]
|
50
|
+
return self.level if my_item
|
51
|
+
items.each do |i|
|
52
|
+
if i.sub_navigation
|
53
|
+
level = i.sub_navigation.level_for_item(navi_key)
|
54
|
+
return level unless level.nil?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return nil
|
58
|
+
end
|
40
59
|
|
41
60
|
# Renders the items in this ItemContainer using the configured renderer.
|
42
61
|
#
|
43
|
-
# Set <tt>include_sub_navigation</tt> to true if you want to nest the sub_navigation into the active
|
44
|
-
def render(
|
45
|
-
self.renderer.new
|
62
|
+
# Set <tt>include_sub_navigation</tt> to true if you want to nest the sub_navigation into the active parent_navigation
|
63
|
+
def render(include_sub_navigation=false)
|
64
|
+
self.renderer.new.render(self, include_sub_navigation)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns true if any of this container's items is selected.
|
68
|
+
#
|
69
|
+
def selected?
|
70
|
+
items.any? {|i| i.selected?}
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the currently selected item, nil if no item is selected.
|
74
|
+
#
|
75
|
+
def selected_item
|
76
|
+
self[current_explicit_navigation] || items.find {|i| i.selected?}
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the current navigation that has been explicitely defined in the controller for this container's level.
|
80
|
+
# Returns nil if no explicit current navigation has been set.
|
81
|
+
#
|
82
|
+
def current_explicit_navigation
|
83
|
+
SimpleNavigation.current_navigation_for(level)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the active item_container for the specified level
|
87
|
+
# (recursively looks up items in selected sub_navigation if level is deeper than this container's level).
|
88
|
+
#
|
89
|
+
def active_item_container_for(desired_level)
|
90
|
+
return self if self.level == desired_level
|
91
|
+
return nil unless selected_sub_navigation?
|
92
|
+
return selected_item.sub_navigation.active_item_container_for(desired_level)
|
46
93
|
end
|
47
94
|
|
48
95
|
private
|
49
96
|
|
97
|
+
def selected_sub_navigation?
|
98
|
+
!!(selected_item && selected_item.sub_navigation)
|
99
|
+
end
|
100
|
+
|
50
101
|
# partially borrowed from ActionSupport::Callbacks
|
51
102
|
def should_add_item?(options) #:nodoc:
|
52
103
|
[options.delete(:if)].flatten.compact.all? { |m| evaluate_method(m) } &&
|
@@ -62,7 +113,6 @@ module SimpleNavigation
|
|
62
113
|
raise ArgumentError, ":if or :unless must be procs or lambdas"
|
63
114
|
end
|
64
115
|
end
|
65
|
-
|
66
116
|
|
67
117
|
end
|
68
118
|
|
@@ -3,14 +3,12 @@ module SimpleNavigation
|
|
3
3
|
|
4
4
|
# This is the base class for all renderers.
|
5
5
|
#
|
6
|
-
# A renderer is responsible for rendering an ItemContainer
|
7
|
-
# It must be initialized with the current_navigation for the rendered ItemContainer and
|
8
|
-
# optionally with the current_sub_navigation (if the sub_navigation will be nested).
|
6
|
+
# A renderer is responsible for rendering an ItemContainer and its containing items to HTML.
|
9
7
|
class Base
|
10
8
|
include ActionView::Helpers::UrlHelper
|
11
9
|
include ActionView::Helpers::TagHelper
|
12
10
|
|
13
|
-
attr_reader :
|
11
|
+
attr_reader :controller
|
14
12
|
|
15
13
|
class << self
|
16
14
|
|
@@ -25,16 +23,18 @@ module SimpleNavigation
|
|
25
23
|
|
26
24
|
controller_method :form_authenticity_token, :protect_against_forgery?, :request_forgery_protection_token
|
27
25
|
|
28
|
-
def initialize
|
29
|
-
@current_navigation = current_navigation
|
30
|
-
@current_sub_navigation = current_sub_navigation
|
26
|
+
def initialize #:nodoc:
|
31
27
|
@controller = SimpleNavigation.controller
|
32
28
|
end
|
33
29
|
|
34
30
|
# Renders the specified ItemContainer to HTML.
|
35
31
|
#
|
36
32
|
# If <tt>include_sub_navigation</tt> is set to true, the renderer should nest the sub_navigation for the active navigation
|
37
|
-
# inside that navigation item.
|
33
|
+
# inside that navigation item.
|
34
|
+
#
|
35
|
+
# A renderer should also take the option SimpleNavigation.config.render_all_levels into account. If it is set to true then it should render all navigation levels
|
36
|
+
# independent of the <tt>include_sub_navigation</tt> option.
|
37
|
+
#
|
38
38
|
def render(item_container, include_sub_navigation=false)
|
39
39
|
raise 'subclass responsibility'
|
40
40
|
end
|