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
@@ -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