krasivotokak-simple-navigation 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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