strikeroff-simple-navigation 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/Manifest +29 -0
- data/README +30 -0
- data/Rakefile +23 -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 +55 -0
- data/init.rb +1 -0
- data/install.rb +5 -0
- data/lib/simple_navigation/configuration.rb +66 -0
- data/lib/simple_navigation/controller_methods.rb +79 -0
- data/lib/simple_navigation/helpers.rb +82 -0
- data/lib/simple_navigation/item.rb +89 -0
- data/lib/simple_navigation/item_container.rb +119 -0
- data/lib/simple_navigation/renderer/base.rb +44 -0
- data/lib/simple_navigation/renderer/list.rb +31 -0
- data/lib/simple_navigation.rb +118 -0
- data/rails/init.rb +3 -0
- data/spec/lib/simple_navigation/configuration_spec.rb +162 -0
- data/spec/lib/simple_navigation/controller_methods_spec.rb +73 -0
- data/spec/lib/simple_navigation/helpers_spec.rb +125 -0
- data/spec/lib/simple_navigation/item_container_spec.rb +315 -0
- data/spec/lib/simple_navigation/item_spec.rb +344 -0
- data/spec/lib/simple_navigation/renderer/base_spec.rb +60 -0
- data/spec/lib/simple_navigation/renderer/list_spec.rb +134 -0
- data/spec/lib/simple_navigation_spec.rb +235 -0
- data/spec/spec_helper.rb +17 -0
- data/strikeroff-simple-navigation.gemspec +33 -0
- data/uninstall.rb +1 -0
- metadata +107 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v2.0.2 add :level=>:all option for render_navigation
|
data/Manifest
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
generators/navigation_config/navigation_config_generator.rb
|
3
|
+
generators/navigation_config/templates/config/navigation.rb
|
4
|
+
generators/navigation_config/USAGE
|
5
|
+
init.rb
|
6
|
+
install.rb
|
7
|
+
lib/simple_navigation/configuration.rb
|
8
|
+
lib/simple_navigation/controller_methods.rb
|
9
|
+
lib/simple_navigation/helpers.rb
|
10
|
+
lib/simple_navigation/item.rb
|
11
|
+
lib/simple_navigation/item_container.rb
|
12
|
+
lib/simple_navigation/renderer/base.rb
|
13
|
+
lib/simple_navigation/renderer/list.rb
|
14
|
+
lib/simple_navigation.rb
|
15
|
+
Manifest
|
16
|
+
rails/init.rb
|
17
|
+
Rakefile
|
18
|
+
README
|
19
|
+
spec/lib/simple_navigation/configuration_spec.rb
|
20
|
+
spec/lib/simple_navigation/controller_methods_spec.rb
|
21
|
+
spec/lib/simple_navigation/helpers_spec.rb
|
22
|
+
spec/lib/simple_navigation/item_container_spec.rb
|
23
|
+
spec/lib/simple_navigation/item_spec.rb
|
24
|
+
spec/lib/simple_navigation/renderer/base_spec.rb
|
25
|
+
spec/lib/simple_navigation/renderer/list_spec.rb
|
26
|
+
spec/lib/simple_navigation_spec.rb
|
27
|
+
spec/spec_helper.rb
|
28
|
+
strikeroff-simple-navigation.gemspec
|
29
|
+
uninstall.rb
|
data/README
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
It is a fork of
|
2
|
+
http://github.com/andi/simple-navigation
|
3
|
+
== Simple Navigation
|
4
|
+
|
5
|
+
Simple Navigation is a plugin for creating a navigation (optionally with sub navigation) for your rails app.
|
6
|
+
|
7
|
+
Source code:
|
8
|
+
git://github.com/andi/simple-navigation.git
|
9
|
+
|
10
|
+
Documentation:
|
11
|
+
http://wiki.github.com/andi/simple-navigation
|
12
|
+
|
13
|
+
Online Demo:
|
14
|
+
http://simple-navigation-demo.andischacke.com
|
15
|
+
|
16
|
+
Discussion Group for Feedback and Questions
|
17
|
+
http://groups.google.com/group/simple-navigation
|
18
|
+
|
19
|
+
|
20
|
+
Diff from original
|
21
|
+
Some times you need to show all navigation tree on page(site map, for example), without config changes
|
22
|
+
Extra level :all can help you
|
23
|
+
|
24
|
+
render_navigation(:level=>:all)
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
Copyright (c) 2009 Andi Schacke, released under the MIT license
|
30
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('strikeroff-simple-navigation') do |p|
|
6
|
+
|
7
|
+
#fork of http://github.com/andi/simple-navigation
|
8
|
+
p.description = "strikeroff-simple-navigation"
|
9
|
+
p.url = "http://github.com/strikeroff"
|
10
|
+
p.author = "Vesov Ilya"
|
11
|
+
p.email = "strikeroff@gmail.com"
|
12
|
+
p.ignore_pattern = ["tmp/*", "script/*", ".svn", ".git"]
|
13
|
+
p.need_tar_gz = false
|
14
|
+
p.retain_gemspec = true
|
15
|
+
p.gemspec_name = 'strikeroff-simple-navigation.gemspec'
|
16
|
+
p.test_pattern = ["test/**/*_test.rb"]
|
17
|
+
p.rdoc_pattern = ["README", "CHANGELOG", "lib/**/*.rb"]
|
18
|
+
p.rdoc_options << "-c utf-8"
|
19
|
+
p.ignore_pattern = [".gitignore", "doc", ".idea", "*.bat", "*.sh"]
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
23
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
Creates a template config file for the simple-navigation plugin. You will find the generated file in config/navigation.rb.
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Configures your navigation
|
2
|
+
SimpleNavigation::Configuration.run do |navigation|
|
3
|
+
# Specify a custom renderer if needed.
|
4
|
+
# The default renderer is SimpleNavigation::Renderer::List which renders HTML lists.
|
5
|
+
# navigation.renderer = Your::Custom::Renderer
|
6
|
+
|
7
|
+
# Specify the class that will be applied to active navigation items. Defaults to 'selected'
|
8
|
+
# navigation.selected_class = 'your_selected_class'
|
9
|
+
|
10
|
+
# Normally only the current sub menu is renderedwhen render_navigation is called
|
11
|
+
# setting this to true render all submenus which is useful for javascript
|
12
|
+
# driven hovering menus like the jquery superfish plugin
|
13
|
+
# navigation.render_all_levels = true
|
14
|
+
|
15
|
+
# Item keys are normally added to list items as id.
|
16
|
+
# This setting turns that off
|
17
|
+
# navigation.autogenerate_item_ids = false
|
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
|
+
|
23
|
+
# Define the primary navigation
|
24
|
+
navigation.items do |primary|
|
25
|
+
# Add an item to the primary navigation. The following params apply:
|
26
|
+
# key - a symbol which uniquely defines your navigation item in the scope of the primary_navigation
|
27
|
+
# name - will be displayed in the rendered navigation. This can also be a call to your I18n-framework.
|
28
|
+
# url - the address that the generated item links to. You can also use url_helpers (named routes, restful routes helper, url_for etc.)
|
29
|
+
# options - can be used to specify attributes that will be included in the rendered navigation item (e.g. id, class etc.)
|
30
|
+
#
|
31
|
+
primary.item :key_1, 'name', url, options
|
32
|
+
|
33
|
+
# Add an item which has a sub navigation (same params, but with block)
|
34
|
+
primary.item :key_2, 'name', url, options do |sub_nav|
|
35
|
+
# Add an item to the sub navigation (same params again)
|
36
|
+
sub_nav.item :key_2_1, 'name', url, options
|
37
|
+
end
|
38
|
+
|
39
|
+
# You can also specify a condition-proc that needs to be fullfilled to display an item.
|
40
|
+
# Conditions are part of the options. They are evaluated in the context of the views,
|
41
|
+
# thus you can use all the methods and vars you have available in the views.
|
42
|
+
primary.item :key_3, 'Admin', url, :class => 'special', :if => Proc.new { current_user.admin? }
|
43
|
+
primary.item :key_4, 'Account', url, :unless => Proc.new { logged_in? }
|
44
|
+
|
45
|
+
# you can also specify a css id or class to attach to this particular level
|
46
|
+
# works for all levels of the menu
|
47
|
+
# primary.dom_id = 'menu-id'
|
48
|
+
# primary.dom_class = 'menu-class'
|
49
|
+
|
50
|
+
# You can turn off auto highlighting for a specific level
|
51
|
+
# primary.auto_highlight = false
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/rails/init"
|
data/install.rb
ADDED
@@ -0,0 +1,66 @@
|
|
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, :render_all_levels, :autogenerate_item_ids, :auto_highlight
|
10
|
+
attr_reader :primary_navigation
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Evals the config_file for the given navigation_context inside the specified context (usually a controller or view)
|
15
|
+
def eval_config(context, navigation_context = :default)
|
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])
|
19
|
+
end
|
20
|
+
|
21
|
+
# Starts processing the configuration
|
22
|
+
def run(&block)
|
23
|
+
block.call Configuration.instance
|
24
|
+
end
|
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
|
+
|
33
|
+
# Extracts a controller from the context.
|
34
|
+
def extract_controller_from(context)
|
35
|
+
if context.respond_to? :controller
|
36
|
+
context.controller
|
37
|
+
else
|
38
|
+
context
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end #class << self
|
43
|
+
|
44
|
+
# Sets the config's default-settings
|
45
|
+
def initialize
|
46
|
+
@renderer = SimpleNavigation::Renderer::List
|
47
|
+
@selected_class = 'selected'
|
48
|
+
@render_all_levels = false
|
49
|
+
@autogenerate_item_ids = true
|
50
|
+
@auto_highlight = true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Yields an SimpleNavigation::ItemContainer for adding navigation items
|
54
|
+
def items(&block)
|
55
|
+
@primary_navigation = ItemContainer.new
|
56
|
+
block.call @primary_navigation
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns true if the config_file has already been evaluated.
|
60
|
+
def loaded?
|
61
|
+
!@primary_navigation.nil?
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#TODO: add :except and :only options to navigation method
|
2
|
+
module SimpleNavigation
|
3
|
+
|
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.
|
7
|
+
#
|
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.
|
10
|
+
#
|
11
|
+
# ==== Examples
|
12
|
+
# class AccountController << ActionController
|
13
|
+
# navigation :account
|
14
|
+
# ...
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class AccountSettingsController << ActionController
|
18
|
+
# navigation :settings
|
19
|
+
# ...
|
20
|
+
# end
|
21
|
+
#
|
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.
|
24
|
+
#
|
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:
|
28
|
+
#
|
29
|
+
# ==== Example
|
30
|
+
# class AccountController << ActionController
|
31
|
+
# navigation :account
|
32
|
+
#
|
33
|
+
# def your_special_action
|
34
|
+
# ...
|
35
|
+
# current_navigation :special
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
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'.
|
40
|
+
#
|
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.
|
44
|
+
module ControllerMethods
|
45
|
+
def self.included(base) #:nodoc:
|
46
|
+
base.class_eval do
|
47
|
+
extend ClassMethods
|
48
|
+
include InstanceMethods
|
49
|
+
include SimpleNavigation::Helpers
|
50
|
+
base.helper_method :render_navigation, :render_primary_navigation, :render_sub_navigation
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
# Sets the active navigation for all actions in this controller.
|
56
|
+
#
|
57
|
+
# The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
|
58
|
+
def navigation(*args)
|
59
|
+
self.class_eval do
|
60
|
+
define_method :sn_set_navigation do
|
61
|
+
current_navigation(*args)
|
62
|
+
end
|
63
|
+
before_filter :sn_set_navigation
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module InstanceMethods
|
69
|
+
# Sets the active navigation. Call this method in any action to override the controller-wide active navigation
|
70
|
+
# specified by navigation.
|
71
|
+
#
|
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
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,82 @@
|
|
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 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
|
+
#
|
9
|
+
# ==== Examples (using Haml)
|
10
|
+
# #primary_navigation= render_navigation(:level => 1)
|
11
|
+
#
|
12
|
+
# #sub_navigation= render_navigation(:level => 2)
|
13
|
+
#
|
14
|
+
# #nested_navigation= render_navigation
|
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.
|
17
|
+
module Helpers
|
18
|
+
|
19
|
+
# Renders the navigation according to the specified options-hash.
|
20
|
+
#
|
21
|
+
# The following options are supported:
|
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
|
26
|
+
# will be loaded and used for rendering the navigation.
|
27
|
+
#
|
28
|
+
def render_navigation(*args)
|
29
|
+
args = [Hash.new] if args.empty?
|
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
|
39
|
+
when :nested
|
40
|
+
SimpleNavigation.primary_navigation.render(true)
|
41
|
+
when :all
|
42
|
+
SimpleNavigation.primary_navigation.render(true,:all=>true)
|
43
|
+
else
|
44
|
+
raise ArgumentError, "Invalid navigation level: #{options[:level]}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Deprecated. Renders the primary_navigation with the configured renderer. Calling render_navigation(:level => 0) has the same effect.
|
49
|
+
def render_primary_navigation(options = {})
|
50
|
+
ActiveSupport::Deprecation.warn("SimpleNavigation::Helpers.render_primary_navigation has been deprected. Please use render_navigation(:level => 1) instead")
|
51
|
+
render_navigation(options.merge(:level => 1))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Deprecated. Renders the sub_navigation with the configured renderer. Calling render_navigation(:level => 1) has the same effect.
|
55
|
+
def render_sub_navigation(options = {})
|
56
|
+
ActiveSupport::Deprecation.warn("SimpleNavigation::Helpers.render_primary_navigation has been deprected. Please use render_navigation(:level => 2) instead")
|
57
|
+
render_navigation(options.merge(:level => 2))
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def extract_backwards_compatible_options(*args)
|
63
|
+
case args.first
|
64
|
+
when Hash
|
65
|
+
options = args.first
|
66
|
+
options[:level] = 1 if options[:level] == :primary
|
67
|
+
options[:level] = 2 if options[:level] == :secondary
|
68
|
+
when Symbol
|
69
|
+
raise ArgumentError, "Invalid arguments" unless [:primary, :secondary, :nested].include? args.first
|
70
|
+
options = Hash.new
|
71
|
+
options[:level] = args.first
|
72
|
+
options[:level] = 1 if options[:level] == :primary
|
73
|
+
options[:level] = 2 if options[:level] == :secondary
|
74
|
+
options.merge!(args[1] || {})
|
75
|
+
else
|
76
|
+
raise ArgumentError, "Invalid arguments"
|
77
|
+
end
|
78
|
+
options
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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, :name, :url, :sub_navigation, :method
|
6
|
+
attr_writer :html_options
|
7
|
+
|
8
|
+
# see ItemContainer#item
|
9
|
+
def initialize(container, key, name, url, options, sub_nav_block) #:nodoc:
|
10
|
+
@container = container
|
11
|
+
@key = key
|
12
|
+
@method = options.delete(:method)
|
13
|
+
@name = name
|
14
|
+
@url = url
|
15
|
+
@html_options = options
|
16
|
+
if sub_nav_block
|
17
|
+
@sub_navigation = ItemContainer.new(@container.level + 1)
|
18
|
+
sub_nav_block.call @sub_navigation
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
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?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the html-options hash for the item, i.e. the options specified for this item in the config-file.
|
34
|
+
# It also adds the 'selected' class to the list of classes if necessary.
|
35
|
+
def html_options
|
36
|
+
default_options = self.autogenerate_item_ids? ? {:id => key.to_s} : {}
|
37
|
+
options = default_options.merge(@html_options)
|
38
|
+
options[:class] = [@html_options[:class], self.selected_class].flatten.compact.join(' ')
|
39
|
+
options.delete(:class) if options[:class].blank?
|
40
|
+
options
|
41
|
+
end
|
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
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
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
|
+
|
80
|
+
def autogenerate_item_ids?
|
81
|
+
SimpleNavigation.config.autogenerate_item_ids
|
82
|
+
end
|
83
|
+
|
84
|
+
def auto_highlight?
|
85
|
+
SimpleNavigation.config.auto_highlight && @container.auto_highlight
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,119 @@
|
|
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
|
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.)
|
23
|
+
#
|
24
|
+
# The <tt>options</tt> can be used to specify the following things:
|
25
|
+
# * <tt>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
|
+
#
|
33
|
+
# The <tt>block</tt> - if specified - will hold the item's sub_navigation.
|
34
|
+
def item(key, name, url, options={}, &block)
|
35
|
+
(@items << SimpleNavigation::Item.new(self, key, name, url, options, block)) if should_add_item?(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the Item with the specified key, nil otherwise.
|
39
|
+
#
|
40
|
+
def [](navi_key)
|
41
|
+
items.find {|i| i.key == navi_key}
|
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
|
59
|
+
|
60
|
+
# Renders the items in this ItemContainer using the configured renderer.
|
61
|
+
#
|
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, options={})
|
64
|
+
self.renderer.new.render(self, include_sub_navigation, options)
|
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)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def selected_sub_navigation?
|
98
|
+
!!(selected_item && selected_item.sub_navigation)
|
99
|
+
end
|
100
|
+
|
101
|
+
# partially borrowed from ActionSupport::Callbacks
|
102
|
+
def should_add_item?(options) #:nodoc:
|
103
|
+
[options.delete(:if)].flatten.compact.all? { |m| evaluate_method(m) } &&
|
104
|
+
![options.delete(:unless)].flatten.compact.any? { |m| evaluate_method(m) }
|
105
|
+
end
|
106
|
+
|
107
|
+
# partially borrowed from ActionSupport::Callbacks
|
108
|
+
def evaluate_method(method) #:nodoc:
|
109
|
+
case method
|
110
|
+
when Proc, Method
|
111
|
+
method.call
|
112
|
+
else
|
113
|
+
raise ArgumentError, ":if or :unless must be procs or lambdas"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SimpleNavigation
|
2
|
+
module Renderer
|
3
|
+
|
4
|
+
# This is the base class for all renderers.
|
5
|
+
#
|
6
|
+
# A renderer is responsible for rendering an ItemContainer and its containing items to HTML.
|
7
|
+
class Base
|
8
|
+
include ActionView::Helpers::UrlHelper
|
9
|
+
include ActionView::Helpers::TagHelper
|
10
|
+
|
11
|
+
attr_reader :controller
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
# Delegates method calls to the controller.
|
16
|
+
def controller_method(*methods)
|
17
|
+
methods.each do |method|
|
18
|
+
delegate method, :to => :controller
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
controller_method :form_authenticity_token, :protect_against_forgery?, :request_forgery_protection_token
|
25
|
+
|
26
|
+
def initialize #:nodoc:
|
27
|
+
@controller = SimpleNavigation.controller
|
28
|
+
end
|
29
|
+
|
30
|
+
# Renders the specified ItemContainer to HTML.
|
31
|
+
#
|
32
|
+
# If <tt>include_sub_navigation</tt> is set to true, the renderer should nest the sub_navigation for the active navigation
|
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
|
+
def render(item_container, include_sub_navigation=false,options={})
|
39
|
+
raise 'subclass responsibility'
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|