simple-navigation 2.7.3 → 3.0.0.beta1

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.
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
@@ -1,12 +1,12 @@
1
1
  module SimpleNavigation
2
-
3
- # Acts as a proxy to navigation items that are passed into the SimpleNavigation::Configuration#items method. It hides the logic
2
+
3
+ # Acts as a proxy to navigation items that are passed into the SimpleNavigation::Configuration#items method. It hides the logic
4
4
  # for finding items from the Configuration object.
5
5
  #
6
6
  class ItemsProvider
7
-
7
+
8
8
  attr_reader :provider
9
-
9
+
10
10
  # It accepts the following types of provider:
11
11
  # * methodname as symbol - the specified method should return the relevant items and has to be available in the view (a helper method)
12
12
  # * object that responds to :items
@@ -17,11 +17,11 @@ module SimpleNavigation
17
17
  def initialize(provider)
18
18
  @provider = provider
19
19
  end
20
-
20
+
21
21
  # Returns the navigation items
22
22
  def items
23
23
  if provider.instance_of?(Symbol)
24
- SimpleNavigation.config.context_for_eval.send(provider)
24
+ SimpleNavigation.context_for_eval.send(provider)
25
25
  elsif provider.respond_to?(:items)
26
26
  provider.items
27
27
  elsif provider.respond_to?(:each)
@@ -30,6 +30,6 @@ module SimpleNavigation
30
30
  raise "items_provider either must be a symbol specifying the helper-method to call, an object with an items-method defined or an enumerable representing the items"
31
31
  end
32
32
  end
33
-
33
+
34
34
  end
35
35
  end
@@ -1,5 +1,52 @@
1
- #TODO: add :except and :only options to navigation method
2
1
  module SimpleNavigation
2
+
3
+ class << self
4
+
5
+ def explicit_navigation_args
6
+ self.adapter.controller.instance_variable_get(:"@sn_current_navigation_args")
7
+ end
8
+
9
+ # Reads the current navigation for the specified level from the controller.
10
+ # Returns nil if there is no current navigation set for level.
11
+ def current_navigation_for(level)
12
+ self.adapter.controller.instance_variable_get(:"@sn_current_navigation_#{level}")
13
+ end
14
+
15
+ # If any navigation has been explicitely set in the controller this method evaluates the specified args set in the controller and sets
16
+ # the correct instance variable in the controller.
17
+ def handle_explicit_navigation
18
+ if SimpleNavigation.explicit_navigation_args
19
+ level, navigation = parse_explicit_navigation_args
20
+ self.adapter.controller.instance_variable_set(:"@sn_current_navigation_#{level}", navigation)
21
+ end
22
+ end
23
+
24
+ # TODO: refactor this ugly thing to make it nice and short
25
+ def parse_explicit_navigation_args
26
+ args = SimpleNavigation.explicit_navigation_args
27
+ args = [Hash.new] if args.empty?
28
+ if args.first.kind_of? Hash
29
+ options = args.first
30
+ else # args is a list of current navigation for several levels
31
+ options = {}
32
+ if args.size == 1 #only one navi-key has been specified, try to find out level
33
+ level = SimpleNavigation.primary_navigation.level_for_item(args.first)
34
+ options[:"level_#{level}"] = args.first if level
35
+ else
36
+ args.each_with_index {|arg, i| options[:"level_#{i + 1}"] = arg}
37
+ end
38
+ end
39
+ #only the deepest level is relevant
40
+ level = options.inject(0) do |max, kv|
41
+ kv.first.to_s =~ /level_(\d)/
42
+ max = $1.to_i if $1.to_i > max
43
+ max
44
+ end
45
+ raise ArgumentError, "Invalid level specified or item key not found" if level == 0
46
+ [level, options[:"level_#{level}"]]
47
+ end
48
+
49
+ end
3
50
 
4
51
  # Adds methods for explicitely setting the current 'active' navigation to the controllers.
5
52
  # Since version 2.0.0 the simple_navigation plugin determines the active navigation based on the current url by default (auto highlighting),
@@ -46,8 +93,6 @@ module SimpleNavigation
46
93
  base.class_eval do
47
94
  extend ClassMethods
48
95
  include InstanceMethods
49
- include SimpleNavigation::Helpers
50
- base.helper_method :render_navigation, :render_primary_navigation, :render_sub_navigation
51
96
  end
52
97
  end
53
98
 
@@ -56,7 +101,6 @@ module SimpleNavigation
56
101
  #
57
102
  # The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
58
103
  def navigation(*args)
59
- ActiveSupport::Deprecation.warn("Setting the active navigation in the controllers has been deprecated. Please use the new :highlights_on option in the config file for explicit highlighting")
60
104
  self.class_eval do
61
105
  define_method :sn_set_navigation do
62
106
  current_navigation(*args)
@@ -73,10 +117,28 @@ module SimpleNavigation
73
117
  #
74
118
  # The specified symbol must match the keys for your navigation items in your config/navigation.rb file.
75
119
  def current_navigation(*args)
76
- ActiveSupport::Deprecation.warn("Setting the active navigation in the controllers has been deprecated. Please use the new :highlights_on option in the config file for explicit highlighting")
77
120
  @sn_current_navigation_args = args
78
121
  end
79
122
  end
80
123
 
81
124
  end
125
+
126
+ class Item
127
+
128
+ def selected_by_config?
129
+ key == SimpleNavigation.current_navigation_for(@container.level)
130
+ end
131
+
132
+ end
133
+
134
+ class ItemContainer
135
+
136
+ def selected_item
137
+ self[SimpleNavigation.current_navigation_for(self.level)] || items.find {|i| i.selected?}
138
+ end
139
+
140
+ end
141
+
82
142
  end
143
+
144
+ ActionController::Base.send(:include, SimpleNavigation::ControllerMethods)
@@ -0,0 +1,10 @@
1
+ require 'simple_navigation/rendering/helpers'
2
+ require 'simple_navigation/rendering/renderer/base'
3
+
4
+ module SimpleNavigation
5
+ module Renderer
6
+ autoload :List, 'simple_navigation/rendering/renderer/list'
7
+ autoload :Links, 'simple_navigation/rendering/renderer/links'
8
+ autoload :Breadcrumbs, 'simple_navigation/rendering/renderer/breadcrumbs'
9
+ end
10
+ end
@@ -1,16 +1,16 @@
1
1
  module SimpleNavigation
2
-
2
+
3
3
  # View helpers to render the navigation.
4
4
  #
5
5
  # Use render_navigation as following to render your navigation:
6
6
  # * call <tt>render_navigation</tt> without :level option to render your complete navigation as nested tree.
7
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
- # * call <tt>render_navigation(:level => 2..3)</tt> to render navigation levels 2 and 3).
8
+ # * call <tt>render_navigation(:level => 2..3)</tt> to render navigation levels 2 and 3).
9
9
  # For example, you could use render_navigation(:level => 1) to render your primary navigation as tabs and render_navigation(:level => 2..3) to render the rest of the navigation as a tree in a sidebar.
10
- #
10
+ #
11
11
  # ==== Examples (using Haml)
12
12
  # #primary_navigation= render_navigation(:level => 1)
13
- #
13
+ #
14
14
  # #sub_navigation= render_navigation(:level => 2)
15
15
  #
16
16
  # #nested_navigation= render_navigation
@@ -18,42 +18,40 @@ module SimpleNavigation
18
18
  # #top_navigation= render_navigation(:level => 1..2)
19
19
  # #sidebar_navigation= render_navigation(:level => 3)
20
20
  module Helpers
21
-
22
- # Renders the navigation according to the specified options-hash.
21
+
22
+ # Renders the navigation according to the specified options-hash.
23
23
  #
24
24
  # The following options are supported:
25
- # * <tt>:level</tt> - defaults to :all which renders the the sub_navigation for an active primary_navigation inside that active primary_navigation item.
25
+ # * <tt>:level</tt> - defaults to :all which renders the the sub_navigation for an active primary_navigation inside that active primary_navigation item.
26
26
  # Specify a specific level to only render that level of navigation (e.g. :level => 1 for primary_navigation etc...).
27
27
  # Specifiy a Range of levels to render only those specific levels (e.g. :level => 1..2 to render both your first and second levels, maybe you want to render your third level somewhere else on the page)
28
28
  # * <tt>:expand_all</tt> - defaults to false. If set to true the all specified levels will be rendered as a fully expanded tree (always open). This is useful for javascript menus like Superfish.
29
29
  # * <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).
30
30
  # 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
31
31
  # will be loaded and used for rendering the navigation.
32
- # * <tt>:items</tt> - you can specify the items directly (e.g. if items are dynamically generated from database). See SimpleNavigation::ItemsProvider for documentation on what to provide as items.
32
+ # * <tt>:items</tt> - you can specify the items directly (e.g. if items are dynamically generated from database). See SimpleNavigation::ItemsProvider for documentation on what to provide as items.
33
33
  # * <tt>:renderer</tt> - specify the renderer to be used for rendering the navigation. Either provide the Class or a symbol matching a registered renderer. Defaults to :list (html list renderer).
34
34
  def render_navigation(*args)
35
35
  args = [Hash.new] if args.empty?
36
36
  options = extract_backwards_compatible_options(*args)
37
37
  options = {:context => :default, :level => :all}.merge(options)
38
38
  ctx = options.delete(:context)
39
- SimpleNavigation.set_template_from self
40
- if SimpleNavigation.config_file?(ctx)
41
- SimpleNavigation.load_config(ctx)
42
- SimpleNavigation::Configuration.eval_config(self, ctx)
43
- end
39
+ SimpleNavigation.init_adapter_from self
40
+ SimpleNavigation.load_config(ctx)
41
+ SimpleNavigation::Configuration.eval_config(ctx)
44
42
  SimpleNavigation.config.items(options[:items]) if options[:items]
45
- SimpleNavigation.handle_explicit_navigation
43
+ SimpleNavigation.handle_explicit_navigation if SimpleNavigation.respond_to?(:handle_explicit_navigation)
46
44
  raise "no primary navigation defined, either use a navigation config file or pass items directly to render_navigation" unless SimpleNavigation.primary_navigation
47
45
  active_item_container = SimpleNavigation.active_item_container_for(options[:level])
48
46
  active_item_container.render(options) unless active_item_container.nil?
49
47
  end
50
-
48
+
51
49
  # Deprecated. Renders the primary_navigation with the configured renderer. Calling render_navigation(:level => 0) has the same effect.
52
50
  def render_primary_navigation(options = {})
53
51
  ActiveSupport::Deprecation.warn("SimpleNavigation::Helpers.render_primary_navigation has been deprecated. Please use render_navigation(:level => 1) instead")
54
52
  render_navigation(options.merge(:level => 1))
55
53
  end
56
-
54
+
57
55
  # Deprecated. Renders the sub_navigation with the configured renderer. Calling render_navigation(:level => 1) has the same effect.
58
56
  def render_sub_navigation(options = {})
59
57
  ActiveSupport::Deprecation.warn("SimpleNavigation::Helpers.render_primary_navigation has been deprecated. Please use render_navigation(:level => 2) instead")
@@ -89,10 +87,10 @@ module SimpleNavigation
89
87
  end
90
88
  options
91
89
  end
92
-
90
+
93
91
  def deprecated_api!
94
92
  ActiveSupport::Deprecation.warn("You are using a deprecated API of SimpleNavigation::Helpers.render_navigation, please check the documentation on http://wiki.github.com/andi/simple-navigation")
95
93
  end
96
-
94
+
97
95
  end
98
96
  end
@@ -1,70 +1,54 @@
1
+ require 'forwardable'
2
+
1
3
  module SimpleNavigation
2
4
  module Renderer
3
-
5
+
4
6
  # This is the base class for all renderers.
5
7
  #
6
8
  # A renderer is responsible for rendering an ItemContainer and its containing items to HTML.
7
9
  class Base
8
- include ActionView::Helpers::UrlHelper
9
- include ActionView::Helpers::TagHelper
10
-
11
- attr_reader :controller, :options
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
10
+ extend Forwardable
11
+
12
+ attr_reader :options, :adapter
25
13
 
14
+ def_delegators :adapter, :link_to, :content_tag
15
+
26
16
  def initialize(options) #:nodoc:
27
17
  @options = options
28
- @controller = SimpleNavigation.controller
18
+ @adapter = SimpleNavigation.adapter
29
19
  end
30
-
20
+
31
21
  def expand_all?
32
22
  !!options[:expand_all]
33
23
  end
34
-
24
+
35
25
  def level
36
26
  options[:level] || :all
37
27
  end
38
-
28
+
39
29
  def skip_if_empty?
40
30
  !!options[:skip_if_empty]
41
- end
42
-
31
+ end
32
+
43
33
  def include_sub_navigation?(item)
44
34
  consider_sub_navigation?(item) && expand_sub_navigation?(item)
45
- end
46
-
35
+ end
36
+
47
37
  def render_sub_navigation_for(item)
48
38
  item.sub_navigation.render(self.options)
49
39
  end
50
-
51
- # Marks the specified input as html_safe (for Rails3). Does nothing if html_safe is not defined on input.
52
- #
53
- def html_safe(input)
54
- input.respond_to?(:html_safe) ? input.html_safe : input
55
- end
56
40
 
57
41
  # Renders the specified ItemContainer to HTML.
58
42
  #
59
43
  # When implementing a renderer, please consider to call include_sub_navigation? to determin
60
44
  # whether an item's sub_navigation should be rendered or not.
61
- #
45
+ #
62
46
  def render(item_container)
63
47
  raise 'subclass responsibility'
64
48
  end
65
-
49
+
66
50
  protected
67
-
51
+
68
52
  def consider_sub_navigation?(item)
69
53
  return false if item.sub_navigation.nil?
70
54
  case level
@@ -77,11 +61,10 @@ module SimpleNavigation
77
61
  end
78
62
  false
79
63
  end
80
-
64
+
81
65
  def expand_sub_navigation?(item)
82
66
  expand_all? || item.selected?
83
67
  end
84
-
85
68
 
86
69
  end
87
70
  end
@@ -1,7 +1,7 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
3
+
4
+ # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
5
5
  # It only renders 'selected' elements.
6
6
  #
7
7
  # By default, the renderer sets the item's key as dom_id for the rendered <a> element unless the config option <tt>autogenerate_item_ids</tt> is set to false.
@@ -9,10 +9,10 @@ module SimpleNavigation
9
9
  # The ItemContainer's dom_class and dom_id are applied to the surrounding <div> element.
10
10
  #
11
11
  class Breadcrumbs < SimpleNavigation::Renderer::Base
12
-
12
+
13
13
  def render(item_container)
14
14
  a_tags = a_tags(item_container)
15
- content_tag(:div, html_safe(a_tags(item_container).join(join_with)), {:id => item_container.dom_id, :class => item_container.dom_class})
15
+ content_tag(:div, a_tags(item_container).join(join_with), {:id => item_container.dom_id, :class => item_container.dom_class})
16
16
  end
17
17
 
18
18
  protected
@@ -20,9 +20,9 @@ module SimpleNavigation
20
20
  def a_tags(item_container)
21
21
  item_container.items.inject([]) do |list, item|
22
22
  if item.selected?
23
- list << link_to(html_safe(item.name), item.url, {:method => item.method}.merge(item.html_options.except(:class,:id))) if item.selected?
23
+ list << link_to(item.name, item.url, {:method => item.method}.merge(item.html_options.except(:class,:id))) if item.selected?
24
24
  if include_sub_navigation?(item)
25
- list.concat a_tags(item.sub_navigation)
25
+ list.concat a_tags(item.sub_navigation)
26
26
  end
27
27
  end
28
28
  list
@@ -33,6 +33,6 @@ module SimpleNavigation
33
33
  @join_with ||= options[:join_with] || " "
34
34
  end
35
35
  end
36
-
36
+
37
37
  end
38
38
  end
@@ -1,7 +1,7 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
3
+
4
+ # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
5
5
  # It adds the 'selected' class to the <a> element that is currently active.
6
6
  #
7
7
  # The Links renderer cannot be used to render nested navigations. If you would like it to use with nested navigations, you have to render each level separately.
@@ -11,15 +11,15 @@ module SimpleNavigation
11
11
  # The ItemContainer's dom_class and dom_id are applied to the surrounding <div> element.
12
12
  #
13
13
  class Links < SimpleNavigation::Renderer::Base
14
-
14
+
15
15
  def render(item_container)
16
16
  div_content = item_container.items.inject([]) do |list, item|
17
- list << link_to(html_safe(item.name), item.url, {:method => item.method}.merge(item.html_options))
17
+ list << link_to(item.name, item.url, {:method => item.method}.merge(item.html_options))
18
18
  end.join
19
- content_tag(:div, html_safe(div_content), {:id => item_container.dom_id, :class => item_container.dom_class})
19
+ content_tag(:div, div_content, {:id => item_container.dom_id, :class => item_container.dom_class})
20
20
  end
21
-
21
+
22
22
  end
23
-
23
+
24
24
  end
25
25
  end
@@ -1,7 +1,7 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders an ItemContainer as a <ul> element and its containing items as <li> elements.
3
+
4
+ # Renders an ItemContainer as a <ul> element and its containing items as <li> elements.
5
5
  # It adds the 'selected' class to li element AND the link inside the li element that is currently active.
6
6
  #
7
7
  # If the sub navigation should be included (based on the level and expand_all options), it renders another <ul> containing the sub navigation inside the active <li> element.
@@ -13,19 +13,19 @@ module SimpleNavigation
13
13
  def render(item_container)
14
14
  list_content = item_container.items.inject([]) do |list, item|
15
15
  html_options = item.html_options
16
- li_content = link_to(html_safe(item.name), item.url, :class => item.selected_class, :method => item.method)
16
+ li_content = link_to(item.name, item.url, :class => item.selected_class, :method => item.method)
17
17
  if include_sub_navigation?(item)
18
18
  li_content << render_sub_navigation_for(item)
19
- end
19
+ end
20
20
  list << content_tag(:li, li_content, html_options)
21
21
  end.join
22
22
  if skip_if_empty? && item_container.empty?
23
23
  ''
24
24
  else
25
- content_tag(:ul, html_safe(list_content), {:id => item_container.dom_id, :class => item_container.dom_class})
25
+ content_tag(:ul, list_content, {:id => item_container.dom_id, :class => item_container.dom_class})
26
26
  end
27
27
  end
28
28
  end
29
-
29
+
30
30
  end
31
31
  end
@@ -1,5 +1 @@
1
- if Rails::VERSION::MAJOR == 3
2
- SimpleNavigation::Initializer::Rails3.run
3
- else
4
- SimpleNavigation::Initializer::Rails2.run
5
- end
1
+ SimpleNavigation.register