krasivotokak-simple-navigation 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
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(key, name, url, options, sub_nav_block)
10
+ @key = key
11
+ @method = options.delete(:method)
12
+ @name = name
13
+ @url = url
14
+ @html_options = options
15
+ if sub_nav_block
16
+ @sub_navigation = ItemContainer.new
17
+ sub_nav_block.call @sub_navigation
18
+ end
19
+ end
20
+
21
+ # Returns true if this navigation item should be rendered as 'selected' for the specified current_navigation.
22
+ def selected?(current_navigation)
23
+ key == current_navigation
24
+ end
25
+
26
+ # Returns the html-options hash for the item, i.e. the options specified for this item in the config-file.
27
+ # It also adds the 'selected' class to the list of classes if necessary.
28
+ def html_options(current_navigation)
29
+ default_class = self.autogenerate_item_ids? ? key.to_s : nil
30
+ @html_options
31
+ @html_options[:class] = [default_class, @html_options[:class], self.selected_class(current_navigation)].flatten.compact.uniq.join(' ')
32
+ @html_options.delete(:class) if @html_options[:class].blank?
33
+ @html_options
34
+ end
35
+
36
+ def selected_class(current_navigation) #:nodoc:
37
+ selected?(current_navigation) ? SimpleNavigation.config.selected_class : nil
38
+ end
39
+
40
+
41
+ protected
42
+
43
+ def autogenerate_item_ids?
44
+ SimpleNavigation.config.autogenerate_item_ids
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,69 @@
1
+ module SimpleNavigation
2
+
3
+ # Holds the Items for a navigation 'level' (either the primary_navigation or a sub_navigation).
4
+ class ItemContainer
5
+
6
+ attr_reader :items
7
+ attr_accessor :renderer, :dom_id, :dom_class
8
+
9
+ def initialize #:nodoc:
10
+ @items = []
11
+ @renderer = Configuration.instance.renderer
12
+ end
13
+
14
+ # Creates a new navigation item.
15
+ #
16
+ # The <tt>key</tt> is a symbol which uniquely defines your navigation item in the scope of the primary_navigation or the sub_navigation.
17
+ #
18
+ # The <tt>name</tt> will be displayed in the rendered navigation. This can also be a call to your I18n-framework.
19
+ #
20
+ # 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.)
21
+ #
22
+ # The <tt>options</tt> can be used to specify the following things:
23
+ # * <tt>html_attributes</tt> - will be included in the rendered navigation item (e.g. id, class etc.)
24
+ # * <tt>:if</tt> - Specifies a proc to call to determine if the item should
25
+ # be rendered (e.g. <tt>:if => Proc.new { current_user.admin? }</tt>). The
26
+ # proc should evaluate to a true or false value and is evaluated in the context of the view.
27
+ # * <tt>:unless</tt> - Specifies a proc to call to determine if the item should not
28
+ # be rendered (e.g. <tt>:unless => Proc.new { current_user.admin? }</tt>). The
29
+ # proc should evaluate to a true or false value and is evaluated in the context of the view.
30
+ #
31
+ # The <tt>block</tt> - if specified - will hold the item's sub_navigation.
32
+ def item(key, name, url, options={}, &block)
33
+ (@items << Item.new(key, name, url, options, block)) if should_add_item?(options)
34
+ end
35
+
36
+ # Returns the Item with the specified key, nil otherwise.
37
+ def [](navi_key)
38
+ items.find {|i| i.key == navi_key}
39
+ end
40
+
41
+ # Renders the items in this ItemContainer using the configured renderer.
42
+ #
43
+ # Set <tt>include_sub_navigation</tt> to true if you want to nest the sub_navigation into the active primary_navigation
44
+ def render(current_navigation, include_sub_navigation=false, current_sub_navigation=nil)
45
+ self.renderer.new(current_navigation, current_sub_navigation).render(self, include_sub_navigation)
46
+ end
47
+
48
+ private
49
+
50
+ # partially borrowed from ActionSupport::Callbacks
51
+ def should_add_item?(options) #:nodoc:
52
+ [options.delete(:if)].flatten.compact.all? { |m| evaluate_method(m) } &&
53
+ ![options.delete(:unless)].flatten.compact.any? { |m| evaluate_method(m) }
54
+ end
55
+
56
+ # partially borrowed from ActionSupport::Callbacks
57
+ def evaluate_method(method) #:nodoc:
58
+ case method
59
+ when Proc, Method
60
+ method.call
61
+ else
62
+ raise ArgumentError, ":if or :unless must be procs or lambdas"
63
+ end
64
+ end
65
+
66
+
67
+ end
68
+
69
+ 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 (primary or a sub_navigation) and its containing items to HTML.
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).
9
+ class Base
10
+ include ActionView::Helpers::UrlHelper
11
+ include ActionView::Helpers::TagHelper
12
+
13
+ attr_reader :current_navigation, :current_sub_navigation, :controller
14
+
15
+ class << self
16
+
17
+ # Delegates method calls to the controller.
18
+ def controller_method(*methods)
19
+ methods.each do |method|
20
+ delegate method, :to => :controller
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ controller_method :form_authenticity_token, :protect_against_forgery?, :request_forgery_protection_token
27
+
28
+ def initialize(current_navigation, current_sub_navigation=nil) #:nodoc:
29
+ @current_navigation = current_navigation
30
+ @current_sub_navigation = current_sub_navigation
31
+ @controller = SimpleNavigation.controller
32
+ end
33
+
34
+ # Renders the specified ItemContainer to HTML.
35
+ #
36
+ # 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.
38
+ def render(item_container, include_sub_navigation=false)
39
+ raise 'subclass responsibility'
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ module SimpleNavigation
2
+ module Renderer
3
+
4
+ # Renders an ItemContainer as a <ul> element and its containing items as <li> elements.
5
+ # It adds the 'selected' class to li element AND the link inside the li element that is currently active.
6
+ # If the sub navigation should be included, it renders another <ul> containing the sub navigation inside the active <li> element.
7
+ #
8
+ # By default, the renderer sets the item's key as dom_id for the rendered <li> element. The id can be explicitely specified by setting
9
+ # the id in the html-options of the 'item' method in the config/navigation.rb file.
10
+ class List < Renderer::Base
11
+
12
+ def render(item_container, include_sub_navigation=false)
13
+ list_content = item_container.items.inject([]) do |list, item|
14
+ html_options = item.html_options(current_navigation)
15
+ li_content = link_to(item.name, item.url, :class => item.selected_class(current_navigation), :method => item.method)
16
+ if item.sub_navigation
17
+ if SimpleNavigation.config.render_all_levels
18
+ li_content << (item.sub_navigation.render(current_sub_navigation))
19
+ else
20
+ li_content << (item.sub_navigation.render(current_sub_navigation)) if include_sub_navigation && item.selected?(current_navigation)
21
+ end
22
+ end
23
+ list << content_tag(:li, li_content, html_options)
24
+ end
25
+ content_tag(:ul, list_content.join, {:class => %(#{item_container.dom_class} #{item_container.dom_id})})
26
+ end
27
+
28
+ end
29
+ end
30
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ default_config_file_path = File.join(RAILS_ROOT, 'config')
2
+ SimpleNavigation.config_file_path = default_config_file_path unless SimpleNavigation.config_file_path
3
+ ActionController::Base.send(:include, SimpleNavigation::ControllerMethods)
@@ -0,0 +1,78 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{simple-navigation}
8
+ s.version = "1.4.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Andi Schacke", "Alexander Semyonov"]
12
+ s.date = %q{2009-08-31}
13
+ s.description = %q{Simple Navigation is a ruby library for creating a navigation (optionally with sub navigation) for your rails app.}
14
+ s.email = %q{andreas.schacke@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "CHANGELOG",
21
+ "CHANGELOG",
22
+ "README",
23
+ "Rakefile",
24
+ "VERSION.yml",
25
+ "generators/navigation_config/USAGE",
26
+ "generators/navigation_config/navigation_config_generator.rb",
27
+ "generators/navigation_config/templates/config/navigation.rb",
28
+ "init.rb",
29
+ "install.rb",
30
+ "lib/simple_navigation.rb",
31
+ "lib/simple_navigation/configuration.rb",
32
+ "lib/simple_navigation/controller_methods.rb",
33
+ "lib/simple_navigation/helpers.rb",
34
+ "lib/simple_navigation/item.rb",
35
+ "lib/simple_navigation/item_container.rb",
36
+ "lib/simple_navigation/renderer/base.rb",
37
+ "lib/simple_navigation/renderer/list.rb",
38
+ "rails/init.rb",
39
+ "simple-navigation.gemspec",
40
+ "spec/lib/simple_navigation/configuration_spec.rb",
41
+ "spec/lib/simple_navigation/controller_methods_spec.rb",
42
+ "spec/lib/simple_navigation/helpers_spec.rb",
43
+ "spec/lib/simple_navigation/item_container_spec.rb",
44
+ "spec/lib/simple_navigation/item_spec.rb",
45
+ "spec/lib/simple_navigation/renderer/base_spec.rb",
46
+ "spec/lib/simple_navigation/renderer/list_spec.rb",
47
+ "spec/lib/simple_navigation_spec.rb",
48
+ "spec/spec_helper.rb",
49
+ "uninstall.rb"
50
+ ]
51
+ s.homepage = %q{http://github.com/andi/simple-navigation}
52
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
53
+ s.require_paths = ["lib"]
54
+ s.rubyforge_project = %q{andi}
55
+ s.rubygems_version = %q{1.3.5}
56
+ s.summary = %q{Simple Navigation is a ruby library for creating a navigation (optionally with sub navigation) for your rails app.}
57
+ s.test_files = [
58
+ "spec/lib/simple_navigation/item_spec.rb",
59
+ "spec/lib/simple_navigation/controller_methods_spec.rb",
60
+ "spec/lib/simple_navigation/item_container_spec.rb",
61
+ "spec/lib/simple_navigation/helpers_spec.rb",
62
+ "spec/lib/simple_navigation/configuration_spec.rb",
63
+ "spec/lib/simple_navigation/renderer/list_spec.rb",
64
+ "spec/lib/simple_navigation/renderer/base_spec.rb",
65
+ "spec/lib/simple_navigation_spec.rb",
66
+ "spec/spec_helper.rb"
67
+ ]
68
+
69
+ if s.respond_to? :specification_version then
70
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
71
+ s.specification_version = 3
72
+
73
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
74
+ else
75
+ end
76
+ else
77
+ end
78
+ end
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe SimpleNavigation::Configuration do
4
+
5
+ before(:each) do
6
+ @config = SimpleNavigation::Configuration.instance
7
+ end
8
+
9
+ describe 'self.run' do
10
+ it "should yield the singleton Configuration object" do
11
+ SimpleNavigation::Configuration.run do |c|
12
+ c.should == @config
13
+ end
14
+ end
15
+ end
16
+
17
+ describe 'self.eval_config' do
18
+ before(:each) do
19
+ @context = mock(:context)
20
+ @context.stub!(:instance_eval)
21
+ @config_files = {:default => 'default', :my_context => 'my_context'}
22
+ SimpleNavigation.stub!(:config_files).and_return(@config_files)
23
+ end
24
+ context "with default navigation context" do
25
+ it "should instance_eval the default config_file-string inside the context" do
26
+ @context.should_receive(:instance_eval).with('default')
27
+ SimpleNavigation::Configuration.eval_config(@context)
28
+ end
29
+ end
30
+ context 'with non default navigation context' do
31
+ it "should instance_eval the specified config_file-string inside the context" do
32
+ @context.should_receive(:instance_eval).with('my_context')
33
+ SimpleNavigation::Configuration.eval_config(@context, :my_context)
34
+ end
35
+ end
36
+ it "should set the controller" do
37
+ @controller = stub(:controller)
38
+ SimpleNavigation::Configuration.should_receive(:extract_controller_from).with(@context).and_return(@controller)
39
+ SimpleNavigation.should_receive(:controller=).with(@controller)
40
+ SimpleNavigation::Configuration.eval_config(@context)
41
+ end
42
+ end
43
+
44
+ describe 'self.extract_controller_from' do
45
+ before(:each) do
46
+ @nav_context = stub(:nav_context)
47
+ end
48
+
49
+ context 'object responds to controller' do
50
+ before(:each) do
51
+ @controller = stub(:controller)
52
+ @nav_context.stub!(:controller).and_return(@controller)
53
+ end
54
+
55
+ it "should return the controller" do
56
+ SimpleNavigation::Configuration.extract_controller_from(@nav_context).should == @controller
57
+ end
58
+
59
+ end
60
+
61
+ context 'object does not respond to controller' do
62
+ it "should return the nav_context" do
63
+ SimpleNavigation::Configuration.extract_controller_from(@nav_context).should == @nav_context
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'initialize' do
69
+ it "should set the List-Renderer as default upon initialize" do
70
+ @config.renderer.should == SimpleNavigation::Renderer::List
71
+ end
72
+ it "should set the selected_class to 'selected' as default" do
73
+ @config.selected_class.should == 'selected'
74
+ end
75
+ it "should set render_all_levels to false as default" do
76
+ @config.render_all_levels.should be_false
77
+ end
78
+ it "should set autogenerate_item_ids to true as default" do
79
+ @config.autogenerate_item_ids.should be_true
80
+ end
81
+ end
82
+ describe 'items' do
83
+ before(:each) do
84
+ @container = stub(:items_container)
85
+ SimpleNavigation::ItemContainer.stub!(:new).and_return(@container)
86
+ end
87
+ it "should should yield an new ItemContainer" do
88
+ @config.items do |container|
89
+ container.should == @container
90
+ end
91
+ end
92
+ it "should assign the ItemContainer to an instance-var" do
93
+ @config.items {}
94
+ @config.primary_navigation.should == @container
95
+ end
96
+ end
97
+
98
+
99
+ end
100
+
101
+
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ ActionController::Base.send(:include, SimpleNavigation::ControllerMethods)
4
+
5
+ describe SimpleNavigation::ControllerMethods do
6
+
7
+ def stub_loading_config
8
+ SimpleNavigation::Configuration.stub!(:load)
9
+ end
10
+
11
+ before(:each) do
12
+ stub_loading_config
13
+ class ApplicationController < ActionController::Base
14
+ end
15
+ @controller = ApplicationController.new
16
+ end
17
+
18
+ describe 'when being included' do
19
+ it "should extend the ClassMethods" do
20
+ @controller.class.should respond_to(:navigation)
21
+ end
22
+ it "should include the InstanceMethods" do
23
+ @controller.should respond_to(:current_navigation)
24
+ end
25
+ it "should install the Helpers Module" do
26
+ [:render_navigation, :render_primary_navigation, :render_sub_navigation].each do |m|
27
+ @controller.master_helper_module.instance_methods.map(&:to_s).should include(m.to_s)
28
+ end
29
+ end
30
+ end
31
+
32
+ describe 'class_methods' do
33
+
34
+ describe 'navigation' do
35
+
36
+ def call_navigation(key1, key2=nil)
37
+ @controller.class_eval do
38
+ navigation key1, key2
39
+ end
40
+ end
41
+
42
+ it "should not have an instance-method 'set_navigation if navigation-method has not been called" do
43
+ @controller.respond_to?(:set_navigation).should be_false
44
+ end
45
+ it 'should create an instance-method "set_navigation" when being called' do
46
+ call_navigation(:key)
47
+ @controller.respond_to?(:set_navigation).should be_true
48
+ end
49
+ it 'the created method should call current_navigation with the specified keys' do
50
+ call_navigation(:primary, :secondary)
51
+ @controller.should_receive(:current_navigation).with(:primary, :secondary)
52
+ @controller.set_navigation
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ describe 'instance_methods' do
59
+
60
+ describe 'current_navigation' do
61
+ it "should set the current_primary_navigation as specified" do
62
+ @controller.current_navigation(:first)
63
+ @controller.instance_variable_get(:@current_primary_navigation).should == :first
64
+ end
65
+ it "should set the current_secondary_navigation as specified" do
66
+ @controller.current_navigation(:first, :second)
67
+ @controller.instance_variable_get(:@current_secondary_navigation).should == :second
68
+ end
69
+ it "should set the current_secondary_navigation to nil if no secondary is specified" do
70
+ @controller.current_navigation(:first)
71
+ @controller.instance_variable_get(:@current_secondary_navigation).should be_nil
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end