simple-navigation 2.7.3 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG +14 -4
  2. data/README +1 -2
  3. data/Rakefile +1 -0
  4. data/VERSION.yml +4 -4
  5. data/generators/navigation_config/templates/config/navigation.rb +14 -14
  6. data/lib/simple_navigation.rb +69 -151
  7. data/lib/simple_navigation/adapters.rb +9 -0
  8. data/lib/simple_navigation/adapters/base.rb +37 -0
  9. data/lib/simple_navigation/adapters/padrino.rb +20 -0
  10. data/lib/simple_navigation/adapters/rails.rb +93 -0
  11. data/lib/simple_navigation/adapters/sinatra.rb +76 -0
  12. data/lib/simple_navigation/core.rb +5 -0
  13. data/lib/simple_navigation/{configuration.rb → core/configuration.rb} +14 -19
  14. data/lib/simple_navigation/{item.rb → core/item.rb} +10 -11
  15. data/lib/simple_navigation/{item_adapter.rb → core/item_adapter.rb} +11 -7
  16. data/lib/simple_navigation/{item_container.rb → core/item_container.rb} +14 -21
  17. data/lib/simple_navigation/{items_provider.rb → core/items_provider.rb} +7 -7
  18. data/lib/simple_navigation/{controller_methods.rb → rails_controller_methods.rb} +67 -5
  19. data/lib/simple_navigation/rendering.rb +10 -0
  20. data/lib/simple_navigation/{helpers.rb → rendering/helpers.rb} +16 -18
  21. data/lib/simple_navigation/{renderer → rendering/renderer}/base.rb +20 -37
  22. data/lib/simple_navigation/{renderer → rendering/renderer}/breadcrumbs.rb +7 -7
  23. data/lib/simple_navigation/{renderer → rendering/renderer}/links.rb +7 -7
  24. data/lib/simple_navigation/{renderer → rendering/renderer}/list.rb +6 -6
  25. data/rails/init.rb +1 -5
  26. data/spec/lib/simple_navigation/adapters/padrino_spec.rb +29 -0
  27. data/spec/lib/simple_navigation/adapters/rails_spec.rb +269 -0
  28. data/spec/lib/simple_navigation/adapters/sinatra_spec.rb +60 -0
  29. data/spec/lib/simple_navigation/{configuration_spec.rb → core/configuration_spec.rb} +7 -18
  30. data/spec/lib/simple_navigation/{item_adapter_spec.rb → core/item_adapter_spec.rb} +11 -11
  31. data/spec/lib/simple_navigation/{item_container_spec.rb → core/item_container_spec.rb} +29 -46
  32. data/spec/lib/simple_navigation/{item_spec.rb → core/item_spec.rb} +30 -64
  33. data/spec/lib/simple_navigation/{items_provider_spec.rb → core/items_provider_spec.rb} +7 -7
  34. data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +251 -0
  35. data/spec/lib/simple_navigation/{helpers_spec.rb → rendering/helpers_spec.rb} +34 -53
  36. data/spec/lib/simple_navigation/{renderer → rendering/renderer}/base_spec.rb +11 -62
  37. data/spec/lib/simple_navigation/{renderer → rendering/renderer}/breadcrumbs_spec.rb +9 -51
  38. data/spec/lib/simple_navigation/rendering/renderer/links_spec.rb +59 -0
  39. data/spec/lib/simple_navigation/{renderer → rendering/renderer}/list_spec.rb +17 -58
  40. data/spec/lib/simple_navigation_spec.rb +51 -298
  41. data/spec/spec_helper.rb +16 -5
  42. metadata +67 -48
  43. data/lib/simple_navigation/initializer.rb +0 -21
  44. data/lib/simple_navigation/railtie.rb +0 -7
  45. data/spec/lib/simple_navigation/controller_methods_spec.rb +0 -90
  46. data/spec/lib/simple_navigation/renderer/links_spec.rb +0 -121
@@ -0,0 +1,20 @@
1
+ module SimpleNavigation
2
+ module Adapters
3
+ class Padrino < Sinatra
4
+
5
+ def self.register
6
+ SimpleNavigation.set_env(PADRINO_ROOT, PADRINO_ENV)
7
+ ::Padrino::Application.send(:helpers, SimpleNavigation::Helpers)
8
+ end
9
+
10
+ def link_to(name, url, options={})
11
+ context.link_to name, url, options
12
+ end
13
+
14
+ def content_tag(type, content, options={})
15
+ context.content_tag type, content, options
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,93 @@
1
+ module SimpleNavigation
2
+ module Adapters
3
+ class Rails < Base
4
+
5
+ attr_reader :controller, :template
6
+
7
+ def self.register
8
+ SimpleNavigation.set_env(rails_root, rails_env)
9
+ ActionController::Base.send(:include, SimpleNavigation::Helpers)
10
+ ActionController::Base.send(:helper_method, :render_navigation)
11
+ end
12
+
13
+ def initialize(context)
14
+ @controller = extract_controller_from context
15
+ @template = template_from @controller
16
+ @request = @template.request if @template
17
+ end
18
+
19
+ def request_uri
20
+ return '' unless request
21
+ return request.fullpath if request.respond_to?(:fullpath)
22
+ request.request_uri
23
+ end
24
+
25
+ def request_path
26
+ return '' unless request
27
+ request.path
28
+ end
29
+
30
+ def context_for_eval
31
+ raise 'no context set for evaluation the config file' unless template || controller
32
+ template || controller
33
+ end
34
+
35
+ def current_page?(url)
36
+ template.current_page?(url) if template
37
+ end
38
+
39
+ def link_to(name, url, options={})
40
+ template.link_to(html_safe(name), url, options) if template
41
+ end
42
+
43
+ def content_tag(type, content, options={})
44
+ template.content_tag(type, html_safe(content), options) if template
45
+ end
46
+
47
+ protected
48
+
49
+ def self.rails_root
50
+ rails3? ? ::Rails.root : ::RAILS_ROOT
51
+ end
52
+
53
+ def self.rails_env
54
+ rails3? ? ::Rails.env : ::RAILS_ENV
55
+ end
56
+
57
+ def self.rails3?
58
+ ::Rails::VERSION::MAJOR == 3
59
+ end
60
+
61
+ def template_from(controller)
62
+ controller.instance_variable_get(:@template) || (controller.respond_to?(:view_context) ? controller.view_context : nil)
63
+ end
64
+
65
+ # Marks the specified input as html_safe (for Rails3). Does nothing if html_safe is not defined on input.
66
+ #
67
+ def html_safe(input)
68
+ input.respond_to?(:html_safe) ? input.html_safe : input
69
+ end
70
+
71
+ # Extracts a controller from the context.
72
+ def extract_controller_from(context)
73
+ if context.respond_to? :controller
74
+ context.controller
75
+ else
76
+ context
77
+ end
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+
84
+ # Initializer for Rails3
85
+ if defined?(Rails) && Rails::VERSION::MAJOR == 3
86
+ module SimpleNavigation
87
+ class Railtie < Rails::Railtie
88
+ initializer "simple_navigation.register" do |app|
89
+ SimpleNavigation.register
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,76 @@
1
+ module SimpleNavigation
2
+ module Adapters
3
+ class Sinatra < Base
4
+
5
+ def self.register
6
+ SimpleNavigation.set_env(sinatra_root, sinatra_environment)
7
+ ::Sinatra::Application.send(:helpers, SimpleNavigation::Helpers)
8
+ end
9
+
10
+ def initialize(context)
11
+ @context = context
12
+ @request = context.request
13
+ end
14
+
15
+ def context_for_eval
16
+ raise 'no context set for evaluation the config file' unless context
17
+ context
18
+ end
19
+
20
+ def request_uri
21
+ request.fullpath
22
+ end
23
+
24
+ def request_path
25
+ request.path
26
+ end
27
+
28
+ def current_page?(url)
29
+ url_string = CGI.unescape(url)
30
+ if url_string.index("?")
31
+ uri = request_uri
32
+ else
33
+ uri = request_uri.split('?').first
34
+ end
35
+ if url_string =~ /^\w+:\/\//
36
+ url_string == "#{request.protocol}#{request.host_with_port}#{uri}"
37
+ else
38
+ url_string == uri
39
+ end
40
+ end
41
+
42
+ def link_to(name, url, options={})
43
+ "<a href='#{url}' #{to_attributes(options)}>#{name}</a>"
44
+ end
45
+
46
+ def content_tag(type, content, options={})
47
+ "<#{type} #{to_attributes(options)}>#{content}</#{type}>"
48
+ end
49
+
50
+ protected
51
+
52
+ def self.sinatra_root
53
+ ::Sinatra::Application.root
54
+ end
55
+
56
+ def self.sinatra_environment
57
+ ::Sinatra::Application.environment
58
+ end
59
+
60
+ def to_attributes(options)
61
+ options.map {|k, v| "#{k}='#{v}'"}.join(' ')
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+
68
+ module SimpleNavigation
69
+
70
+ # Adds registered method to SimpleNavigation. This is called when executing 'register SimpleNavigation'.
71
+ def self.registered(app)
72
+ register
73
+ app.helpers Helpers
74
+ end
75
+
76
+ end
@@ -0,0 +1,5 @@
1
+ require 'simple_navigation/core/configuration'
2
+ require 'simple_navigation/core/item_adapter'
3
+ require 'simple_navigation/core/item'
4
+ require 'simple_navigation/core/item_container'
5
+ require 'simple_navigation/core/items_provider'
@@ -1,29 +1,28 @@
1
1
  require 'singleton'
2
2
 
3
3
  module SimpleNavigation
4
-
5
- # Responsible for evaluating and handling the config/navigation.rb file.
4
+
5
+ # Responsible for evaluating and handling the config/navigation.rb file.
6
6
  class Configuration
7
7
  include Singleton
8
-
8
+
9
9
  attr_accessor :renderer, :selected_class, :autogenerate_item_ids, :id_generator, :auto_highlight
10
10
  attr_reader :render_all_levels, :primary_navigation
11
11
 
12
12
  class << self
13
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.set_template_from context
14
+ # Evals the config_file for the given navigation_context
15
+ def eval_config(navigation_context = :default)
17
16
  SimpleNavigation.context_for_eval.instance_eval(SimpleNavigation.config_files[navigation_context])
18
17
  end
19
-
18
+
20
19
  # Starts processing the configuration
21
20
  def run(&block)
22
21
  block.call Configuration.instance
23
- end
24
-
22
+ end
23
+
25
24
  end #class << self
26
-
25
+
27
26
  # Sets the config's default-settings
28
27
  def initialize
29
28
  @renderer = SimpleNavigation.default_renderer || SimpleNavigation::Renderer::List
@@ -32,17 +31,17 @@ module SimpleNavigation
32
31
  @id_generator = Proc.new {|id| id.to_s }
33
32
  @auto_highlight = true
34
33
  end
35
-
34
+
36
35
  # Adds a deprecation warning when this options is set in the config file
37
36
  def render_all_levels=(do_it)
38
37
  ActiveSupport::Deprecation.warn("Setting render_all_levels in the config-file has been deprected. Please use render_navigation(:expand_all => true) instead")
39
38
  @render_all_levels = do_it
40
39
  end
41
-
40
+
42
41
  # This is the main method for specifying the navigation items. It can be used in two ways:
43
- #
42
+ #
44
43
  # 1. Declaratively specify your items in the config/navigation.rb file using a block. It then yields an SimpleNavigation::ItemContainer for adding navigation items.
45
- # 1. Directly provide your items to the method (e.g. when loading your items from the database). Either specify
44
+ # 1. Directly provide your items to the method (e.g. when loading your items from the database). Either specify
46
45
  #
47
46
  # ==== Example for block style
48
47
  # config.items do |primary|
@@ -66,15 +65,11 @@ module SimpleNavigation
66
65
  @primary_navigation.items = SimpleNavigation::ItemsProvider.new(items_provider).items
67
66
  end
68
67
  end
69
-
68
+
70
69
  # Returns true if the config_file has already been evaluated.
71
70
  def loaded?
72
71
  !@primary_navigation.nil?
73
72
  end
74
-
75
- def context_for_eval
76
- self.class.context_for_eval
77
- end
78
73
 
79
74
  end
80
75
 
@@ -1,13 +1,13 @@
1
1
  module SimpleNavigation
2
-
2
+
3
3
  # Represents an item in your navigation. Gets generated by the item method in the config-file.
4
4
  class Item
5
5
  attr_reader :key, :name, :url, :sub_navigation, :method, :highlights_on
6
6
  attr_writer :html_options
7
-
7
+
8
8
  # see ItemContainer#item
9
9
  #
10
- # The subnavigation (if any) is either provided by a block or passed in directly as <tt>items</tt>
10
+ # The subnavigation (if any) is either provided by a block or passed in directly as <tt>items</tt>
11
11
  def initialize(container, key, name, url, options, items=nil, &sub_nav_block)
12
12
  @container = container
13
13
  @key = key
@@ -22,7 +22,7 @@ module SimpleNavigation
22
22
  @sub_navigation.items = items if items
23
23
  end
24
24
  end
25
-
25
+
26
26
  # Returns true if this navigation item should be rendered as 'selected'.
27
27
  # An item is selected if
28
28
  #
@@ -33,14 +33,14 @@ module SimpleNavigation
33
33
  def selected?
34
34
  @selected = @selected || selected_by_config? || selected_by_subnav? || selected_by_url?
35
35
  end
36
-
36
+
37
37
  # Returns the html-options hash for the item, i.e. the options specified for this item in the config-file.
38
- # It also adds the 'selected' class to the list of classes if necessary.
38
+ # It also adds the 'selected' class to the list of classes if necessary.
39
39
  def html_options
40
40
  default_options = self.autogenerate_item_ids? ? {:id => autogenerated_item_id} : {}
41
41
  options = default_options.merge(@html_options)
42
42
  options[:class] = [@html_options[:class], self.selected_class].flatten.compact.join(' ')
43
- options.delete(:class) if options[:class].blank?
43
+ options.delete(:class) if options[:class].nil? || options[:class] == ''
44
44
  options
45
45
  end
46
46
 
@@ -57,9 +57,8 @@ module SimpleNavigation
57
57
  sub_navigation && sub_navigation.selected?
58
58
  end
59
59
 
60
- # Return true if item has explicitly selected in controllers
61
60
  def selected_by_config?
62
- key == @container.current_explicit_navigation
61
+ false
63
62
  end
64
63
 
65
64
  # Returns true if the item's url matches the request's current url.
@@ -68,7 +67,7 @@ module SimpleNavigation
68
67
  raise ArgumentError, ':highlights_on must be a regexp' unless highlights_on.instance_of?(Regexp)
69
68
  SimpleNavigation.request_uri =~ highlights_on
70
69
  elsif auto_highlight?
71
- !!(root_path_match? || (SimpleNavigation.template && SimpleNavigation.template.current_page?(url)))
70
+ !!(root_path_match? || SimpleNavigation.current_page?(url))
72
71
  else
73
72
  false
74
73
  end
@@ -76,7 +75,7 @@ module SimpleNavigation
76
75
 
77
76
  # Returns true if both the item's url and the request's url are root_path
78
77
  def root_path_match?
79
- url == '/' && SimpleNavigation.controller.request.path == '/'
78
+ url == '/' && SimpleNavigation.request_path == '/'
80
79
  end
81
80
 
82
81
  # Returns true if the item's id should be added to the rendered output.
@@ -1,5 +1,7 @@
1
+ require 'forwardable'
2
+
1
3
  module SimpleNavigation
2
-
4
+
3
5
  # This class acts as an adapter to items that are not defined using the DSL in the config/navigation.rb, but directly provided inside the application.
4
6
  # When defining the items that way, every item you provide needs to define the following methods:
5
7
  #
@@ -8,34 +10,36 @@ module SimpleNavigation
8
10
  # * <tt>url</tt>
9
11
  #
10
12
  # and optionally
11
- #
13
+ #
12
14
  # * <tt>options</tt>
13
15
  # * <tt>items</tt> - if one of your items has a subnavigation it must respond to <tt>items</tt> providing the subnavigation.
14
16
  #
15
17
  # See SimpleNavigation::ItemContainer#item for the purpose of these methods.
16
18
  class ItemAdapter
17
- delegate :key, :name, :url, :to => :item
19
+ extend Forwardable
18
20
 
21
+ def_delegators :item, :key, :name, :url
22
+
19
23
  attr_reader :item
20
24
 
21
25
  def initialize(item)
22
26
  @item = item
23
27
  end
24
-
28
+
25
29
  # Returns the options for this item. If the wrapped item does not implement an options method, an empty hash is returned.
26
30
  def options
27
31
  @item.respond_to?(:options) ? @item.options : {}
28
32
  end
29
-
33
+
30
34
  # Returns the items (subnavigation) for this item if it responds to :items and the items-collection is not empty. Returns nil otherwise.
31
35
  def items
32
36
  (@item.respond_to?(:items) && !(@item.items.nil? || @item.items.empty?)) ? @item.items : nil
33
37
  end
34
-
38
+
35
39
  # Converts this Item into a SimpleNavigation::Item
36
40
  def to_simple_navigation_item(item_container)
37
41
  SimpleNavigation::Item.new(item_container, key, name, url, options, items)
38
42
  end
39
-
43
+
40
44
  end
41
45
  end
@@ -1,25 +1,25 @@
1
1
  module SimpleNavigation
2
-
2
+
3
3
  # Holds the Items for a navigation 'level'.
4
4
  class ItemContainer
5
-
5
+
6
6
  attr_reader :items, :level
7
7
  attr_accessor :renderer, :dom_id, :dom_class, :auto_highlight
8
-
8
+
9
9
  def initialize(level=1) #:nodoc:
10
10
  @level = level
11
11
  @items = []
12
12
  @renderer = SimpleNavigation.config.renderer
13
13
  @auto_highlight = true
14
14
  end
15
-
16
- # Creates a new navigation item.
15
+
16
+ # Creates a new navigation item.
17
17
  #
18
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
- #
19
+ #
20
20
  # The <tt>name</tt> will be displayed in the rendered navigation. This can also be a call to your I18n-framework.
21
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.)
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
23
  #
24
24
  # The <tt>options</tt> can be used to specify the following things:
25
25
  # * <tt>any html_attributes</tt> - will be included in the rendered navigation item (e.g. id, class etc.)
@@ -30,7 +30,7 @@ module SimpleNavigation
30
30
  # be rendered (e.g. <tt>:unless => Proc.new { current_user.admin? }</tt>). The
31
31
  # proc should evaluate to a true or false value and is evaluated in the context of the view.
32
32
  # * <tt>:method</tt> - Specifies the http-method for the generated link - default is :get.
33
- # * <tt>:highlights_on</tt> - if autohighlighting is turned off and/or you want to explicitly specify
33
+ # * <tt>:highlights_on</tt> - if autohighlighting is turned off and/or you want to explicitly specify
34
34
  # when the item should be highlighted, you can set a regexp which is matched againstthe current URI.
35
35
  #
36
36
  # The <tt>block</tt> - if specified - will hold the item's sub_navigation.
@@ -66,7 +66,7 @@ module SimpleNavigation
66
66
  end
67
67
  return nil
68
68
  end
69
-
69
+
70
70
  # Renders the items in this ItemContainer using the configured renderer.
71
71
  #
72
72
  # The options are the same as in the view's render_navigation call (they get passed on)
@@ -92,14 +92,7 @@ module SimpleNavigation
92
92
  # Returns the currently selected item, nil if no item is selected.
93
93
  #
94
94
  def selected_item
95
- self[current_explicit_navigation] || items.find {|i| i.selected?}
96
- end
97
-
98
- # Returns the current navigation that has been explicitely defined in the controller for this container's level.
99
- # Returns nil if no explicit current navigation has been set.
100
- #
101
- def current_explicit_navigation
102
- SimpleNavigation.current_navigation_for(level)
95
+ items.find {|i| i.selected?}
103
96
  end
104
97
 
105
98
  # Returns the active item_container for the specified level
@@ -117,7 +110,7 @@ module SimpleNavigation
117
110
  end
118
111
 
119
112
  private
120
-
113
+
121
114
  def selected_sub_navigation?
122
115
  !!(selected_item && selected_item.sub_navigation)
123
116
  end
@@ -127,7 +120,7 @@ module SimpleNavigation
127
120
  [options.delete(:if)].flatten.compact.all? { |m| evaluate_method(m) } &&
128
121
  ![options.delete(:unless)].flatten.compact.any? { |m| evaluate_method(m) }
129
122
  end
130
-
123
+
131
124
  # partially borrowed from ActionSupport::Callbacks
132
125
  def evaluate_method(method) #:nodoc:
133
126
  case method
@@ -137,7 +130,7 @@ module SimpleNavigation
137
130
  raise ArgumentError, ":if or :unless must be procs or lambdas"
138
131
  end
139
132
  end
140
-
133
+
141
134
  end
142
-
135
+
143
136
  end