semantic_navigation 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/.travis.yml +7 -0
  2. data/Changelog.md +7 -0
  3. data/README.md +25 -8
  4. data/Rakefile +2 -0
  5. data/gemfiles/rails3 +7 -0
  6. data/lib/generators/semantic_navigation/install/templates/semantic_navigation.rb +6 -2
  7. data/lib/semantic_navigation/configuration.rb +5 -0
  8. data/lib/semantic_navigation/core/base.rb +2 -2
  9. data/lib/semantic_navigation/core/leaf.rb +28 -10
  10. data/lib/semantic_navigation/core/navigation.rb +11 -4
  11. data/lib/semantic_navigation/core/node.rb +24 -12
  12. data/lib/semantic_navigation/helper_methods.rb +3 -1
  13. data/lib/semantic_navigation/renderers/bread_crumb.rb +3 -3
  14. data/lib/semantic_navigation/renderers/list.rb +2 -2
  15. data/lib/semantic_navigation/renderers/render_helpers.rb +6 -2
  16. data/lib/semantic_navigation/twitter_bootstrap/breadcrumb.rb +4 -4
  17. data/lib/semantic_navigation/twitter_bootstrap/list.rb +6 -6
  18. data/lib/semantic_navigation/twitter_bootstrap/tabs.rb +3 -3
  19. data/lib/semantic_navigation/version.rb +1 -1
  20. data/spec/lib/semantic_navigation/configuration_spec.rb +153 -0
  21. data/spec/lib/semantic_navigation/core/leaf_spec.rb +50 -0
  22. data/spec/lib/semantic_navigation/core/navigation_spec.rb +35 -0
  23. data/spec/lib/semantic_navigation/core/node_spec.rb +25 -0
  24. data/spec/lib/semantic_navigation/helper_methods_spec.rb +82 -0
  25. data/spec/lib/semantic_navigation/renderers/bread_crumb_spec.rb +203 -0
  26. data/spec/lib/semantic_navigation/renderers/list_spec.rb +241 -0
  27. data/spec/lib/semantic_navigation/twitter_bootstrap/breadcrumb_spec.rb +202 -0
  28. data/spec/lib/semantic_navigation/twitter_bootstrap/list_spec.rb +316 -0
  29. data/spec/lib/semantic_navigation/twitter_bootstrap/tabs_spec.rb +310 -0
  30. data/spec/spec_helper.rb +1 -0
  31. metadata +15 -9
  32. data/spec/lib/semantic_navigation/core/base_spec.rb +0 -1
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - ruby-head
6
+ gemfile:
7
+ - gemfiles/rails3
data/Changelog.md CHANGED
@@ -1,3 +1,10 @@
1
+ ### 0.0.14
2
+ * Now in render_if proc there is possibility to catch self(rendering element)
3
+ * Items accept procs for links definitions
4
+ * Fixed bug in active_item_for method
5
+ * active_item_for now returns empty string instead of nil then no active items
6
+ * added multiname support for items
7
+
1
8
  ### 0.0.13 / August 14, 2012
2
9
 
3
10
  * Bugfixes for support array of route like links
data/README.md CHANGED
@@ -1,13 +1,20 @@
1
1
  This is semantic_navigation gem
2
2
 
3
3
  ###Purpose
4
- This gem generates the navigation for your Rails app.
5
- Really customizable and simple to use.
6
- Using this gem you have 4 types of renderers: menu, breadcrumb, tabs, and, pills
4
+ Forget fat layouts, views and controllers. This gem will do all the menu staff for you.
5
+ You simply just have to generate configuration file, fill it with your menu hierarchy and renderer it wherever you want.
7
6
 
8
- You can define different menus and render them separate.
7
+ Symply and customizable it will make for you all the routings you were spending a lot of time before.
9
8
 
10
- Now with simple integration with a twitter-bootstrap CSS framework.
9
+ * semantic_navigation supports defining as many separate menus as you want and they can be as deep as you need.
10
+ * supports different styles of url definitions ('route#like', :symbols, 'strings', {hash: 'like'})
11
+ * supports and array of urls for one item
12
+ * supports procs for item name definitions - so you can have dynamic names
13
+ * supports render conditions defined as proc where you have access to controller class variables, request params and even to the rendering item
14
+ * supports multiname definitions where you can set the custom name for each renderer.
15
+ * has renderers compatible with bootstrap - so if you using bootstrap it will be simplier
16
+ * supports controller default styles overriding both - from configuration and view file
17
+ * supports custom renderers
11
18
 
12
19
  ###How to install
13
20
 
@@ -33,9 +40,9 @@ Configure your navigation in config/semantic_navigation.rb
33
40
  <pre><code>
34
41
  SemanticNavigation::Configuration.run do
35
42
  navigate :root_menu do
36
- item :header_item, nil, :name => 'Header'
43
+ header :header_item, :name => 'Header'
37
44
  item :first_item, '#', :name => 'First Item', :ico => :tag
38
- item :divide
45
+ divider
39
46
  item :second_item, '#', :name => 'Second Item', :ico => :user
40
47
  end
41
48
  end
@@ -46,7 +53,17 @@ And try to render it in your layout(code in haml):
46
53
  .well
47
54
  = navigation_for :root_menu, :as => :bootstrap_list
48
55
  </code></pre>
56
+ or
57
+ <pre><code>
58
+ .well
59
+ = bootstrap_list_for :root_menu
60
+ </code></pre>
49
61
 
50
62
  Render the navigation using the semantic_navigation helper methods and options for them.
51
63
 
52
- For the information of how to configure and render your navigation read the <a href='https://github.com/fr33z3/semantic_navigation/wiki'>Wiki</a>
64
+ For the information of how to configure and render your navigation read the <a href='https://github.com/fr33z3/semantic_navigation/wiki'>Wiki</a>
65
+
66
+ Dependence:
67
+
68
+ * Ruby >= 1.9.2
69
+ * Rails >= 3.0.0
data/Rakefile CHANGED
@@ -2,3 +2,5 @@ require 'rspec/core/rake_task'
2
2
  require "bundler/gem_tasks"
3
3
 
4
4
  RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
data/gemfiles/rails3 ADDED
@@ -0,0 +1,7 @@
1
+ source :rubygems
2
+
3
+ gem 'semantic_navigation', :path => '..'
4
+ gem 'rails', '>=3.1.0'
5
+ gem 'rspec'
6
+ gem 'rake'
7
+ gem 'simplecov'
@@ -1,23 +1,27 @@
1
+ #encoding: utf-8
1
2
  SemanticNavigation::Configuration.run do
2
3
  # Read wiki https://github.com/fr33z3/semantic_navigation/wiki to lear about
3
4
  # semantic_navigation configuration
4
5
 
6
+ #Override renderer default styles:
5
7
  #styles_for :list do
6
8
  # show_navigation_active_class true
7
9
  # navigation_active_class [:some_active_class]
8
10
  #end
9
11
 
12
+ # You can register your custom renderer:
10
13
  #register_renderer :some_renderer, SomeRendererClass
11
14
 
15
+ # The example of the navigation:
12
16
  #navigate :navigation do
13
- # item :header_item, :name => 'Header Item'
17
+ # header :header_item, :name => 'Header Item'
14
18
  # item :first_item, :first_item_route, :ico => 'user' do
15
19
  # item :sub_item, :sub_item_route do
16
20
  # item :sub_sub_item, :sub_sub_item_route
17
21
  # end
18
22
  # item :second_sub, :second_sub_route, :ico => 'user'
19
23
  # end
20
- # item :divide
24
+ # divider
21
25
  # item :second_item, :second_item_route
22
26
  #end
23
27
 
@@ -25,6 +25,7 @@ module SemanticNavigation
25
25
  renderer.instance_eval &@@render_styles[renderer_name]
26
26
  end
27
27
  options.keys.each{|key| renderer.send "#{key}=", options[key]}
28
+ renderer.name = renderer_name
28
29
  navigation = @@navigations[menu_id]
29
30
  navigation.mark_active
30
31
  navigation.render(renderer)
@@ -54,6 +55,10 @@ module SemanticNavigation
54
55
  def self.view_object
55
56
  @@view_object
56
57
  end
58
+
59
+ def self.view_object=(view_object)
60
+ @@view_object = view_object
61
+ end
57
62
 
58
63
  def self.navigation(name)
59
64
  @@navigations[name]
@@ -2,11 +2,11 @@ module SemanticNavigation
2
2
  module Core
3
3
  class Base
4
4
 
5
- attr :id, :level, :classes, :active
5
+ attr_accessor :id, :level, :classes, :active
6
6
  attr_writer :render_if
7
7
 
8
8
  def render_if
9
- !@render_if.nil? ? view_object.instance_eval(&@render_if) : true
9
+ !@render_if.nil? ? view_object.instance_exec(self, &@render_if) : true
10
10
  end
11
11
 
12
12
  def initialize(options, level)
@@ -1,32 +1,50 @@
1
1
  module SemanticNavigation
2
2
  module Core
3
3
  class Leaf < Base
4
- attr :link_classes
4
+ attr_accessor :link_classes
5
5
 
6
6
  def url
7
- @url.is_a?(Array) ? @url.first : @url
7
+ urls.first
8
8
  end
9
9
 
10
10
  def initialize(options, level)
11
11
  super options, level
12
12
  end
13
13
 
14
- def name
15
- rendering_name = @name || I18n.t("#{@i18n_name}.#{@id}", :default => '')
16
- if rendering_name.is_a?(Proc)
17
- view_object.instance_eval(&rendering_name).to_s
18
- else
19
- rendering_name
20
- end
14
+ def name(renderer_name = nil)
15
+ rendering_name = @name
16
+ rendering_name = rendering_name[renderer_name.to_sym] || rendering_name[:default] if rendering_name.is_a?(Hash)
17
+ rendering_name = view_object.instance_eval(&rendering_name).to_s if rendering_name.is_a?(Proc)
18
+ rendering_name || i18n_name(renderer_name)
21
19
  end
22
20
 
23
21
  def mark_active
24
22
  if @url
25
- @active = [@url].flatten(1).map{|u| current_page?(u) rescue false}.reduce(:"|")
23
+ @active = urls.map{|u| current_page?(u) rescue false}.reduce(:"|")
26
24
  else
27
25
  @active = false
28
26
  end
29
27
  end
28
+
29
+ private
30
+
31
+ def i18n_name(renderer_name = nil)
32
+ name = I18n.t("#{@i18n_name}.#{@id}", :default => '')
33
+ if name.is_a? Hash
34
+ name = name[renderer_name.to_sym] || name[:default]
35
+ end
36
+ name || ''
37
+ end
38
+
39
+ def urls
40
+ [@url].flatten(1).map do |url|
41
+ if url.is_a?(Proc)
42
+ view_object.instance_eval(&url) rescue ''
43
+ else
44
+ url
45
+ end
46
+ end
47
+ end
30
48
 
31
49
  end
32
50
  end
@@ -1,7 +1,7 @@
1
1
  module SemanticNavigation
2
2
  module Core
3
3
  class Navigation < Base
4
- attr :sub_elements
4
+ attr_accessor :sub_elements
5
5
 
6
6
  def initialize(options, level = 0)
7
7
  @sub_elements = []
@@ -24,6 +24,13 @@ module SemanticNavigation
24
24
  element.instance_eval &block
25
25
  else
26
26
  element = Leaf.new(options, @level+1)
27
+ #Deprecation warning message
28
+ #TODO:Should be deleted after moving the header and divider definition via item
29
+ if element.url.nil? && !element.name.empty?
30
+ puts 'Warning: do not define `headers` using `item` method. Use `header` instead. This logic will be deprecated soon.'
31
+ elsif element.url.nil? && element.name.empty?
32
+ puts 'Warning: do not define `dividers` using `item` method. Use `divider` instead. This logic will be deprecated soon.'
33
+ end
27
34
  end
28
35
 
29
36
  @sub_elements.push element
@@ -64,10 +71,10 @@ module SemanticNavigation
64
71
  if url.is_a? String
65
72
  controller_name, action_name = url.split('#')
66
73
  if controller_name && action_name
67
- url = {:controller => controller_name, :action => action_name}
68
- end
74
+ decoded_url = {:controller => controller_name, :action => action_name}
75
+ end
69
76
  end
70
- url
77
+ decoded_url || url
71
78
  end
72
79
 
73
80
  end
@@ -1,10 +1,10 @@
1
1
  module SemanticNavigation
2
2
  module Core
3
3
  class Node < Navigation
4
- attr :link_classes, :node_classes
4
+ attr_accessor :link_classes, :node_classes
5
5
 
6
6
  def url
7
- @url.is_a?(Array) ? @url.first : @url
7
+ urls.first
8
8
  end
9
9
 
10
10
  def initialize(options, level)
@@ -12,25 +12,37 @@ module SemanticNavigation
12
12
  super options, level
13
13
  end
14
14
 
15
- def name
16
- rendering_name = @name || i18n_name
17
- if rendering_name.is_a?(Proc)
18
- view_object.instance_eval(&rendering_name).to_s
19
- else
20
- rendering_name
21
- end
15
+ def name(renderer_name = nil)
16
+ rendering_name = @name
17
+ rendering_name = rendering_name[renderer_name.to_sym] || rendering_name[:default] if rendering_name.is_a?(Hash)
18
+ rendering_name = view_object.instance_eval(&rendering_name).to_s if rendering_name.is_a?(Proc)
19
+ rendering_name || i18n_name(renderer_name)
22
20
  end
23
21
 
24
22
  def mark_active
25
23
  @sub_elements.each{|element| element.mark_active}
26
- @active = [@url].flatten(1).map{|u| current_page?(u) rescue false}.reduce(:"|")
24
+ @active = urls.map{|u| current_page?(u) rescue false}.reduce(:"|")
27
25
  @active |= !@sub_elements.find{|element| element.active}.nil?
28
26
  end
29
27
 
30
28
  private
31
29
 
32
- def i18n_name
33
- I18n.t("#{@i18n_name}.#{@id}", :default => '')
30
+ def i18n_name(renderer_name = nil)
31
+ name = I18n.t("#{@i18n_name}.#{@id}", :default => '')
32
+ if name.is_a? Hash
33
+ name = name[renderer_name.to_sym] || name[:default]
34
+ end
35
+ name || ''
36
+ end
37
+
38
+ def urls
39
+ [@url].flatten(1).map do |url|
40
+ if url.is_a?(Proc)
41
+ view_object.instance_eval(&url) rescue ''
42
+ else
43
+ url
44
+ end
45
+ end
34
46
  end
35
47
 
36
48
  end
@@ -7,13 +7,15 @@ module SemanticNavigation::HelperMethods
7
7
  end
8
8
 
9
9
  def active_item_for(name, level = nil)
10
+ SemanticNavigation::Configuration.view_object = self
10
11
  navigation = SemanticNavigation::Configuration.navigation(name)
12
+ navigation.mark_active
11
13
  item = navigation
12
14
  while !item.is_a?(SemanticNavigation::Core::Leaf) &&
13
15
  !item.sub_elements.find{|e| e.active}.nil? &&
14
16
  (!level.nil? ? item.level < level : true)
15
17
  item = item.sub_elements.find{|e| e.active}
16
18
  end
17
- item.name if item != navigation
19
+ item != navigation ? item.name(:active_item_for) : ''
18
20
  end
19
21
  end
@@ -25,7 +25,7 @@ module SemanticNavigation
25
25
  def node(object)
26
26
  content_tag(:li, nil, :id => show_id(:leaf, object.id),
27
27
  :class => merge_classes(:leaf, object.active, object.classes)) do
28
- link_to(object.name, object.url, :id => show_id(:link, object.id),
28
+ link_to(object_name(object), object.url, :id => show_id(:link, object.id),
29
29
  :class => merge_classes(:link, object.active, object.link_classes))
30
30
  end +
31
31
  content_tag(:li) do
@@ -38,10 +38,10 @@ module SemanticNavigation
38
38
  content_tag :li, nil, :id => show_id(:leaf, object.id),
39
39
  :class => merge_classes(:leaf, object.active, object.classes) do
40
40
  if last_as_link
41
- link_to object.name, object.url, :id => show_id(:link, object.id),
41
+ link_to object_name(object), object.url, :id => show_id(:link, object.id),
42
42
  :class => merge_classes(:link, object.active, object.link_classes)
43
43
  else
44
- object.name
44
+ object_name(object)
45
45
  end
46
46
  end
47
47
  end
@@ -18,7 +18,7 @@ module SemanticNavigation
18
18
  def node(object)
19
19
  content_tag :li, nil, :id => show_id(:leaf, object.id),
20
20
  :class => merge_classes(:leaf, object.active, object.classes) do
21
- link_to(object.name, object.url, :id => show_id(:link, object.id),
21
+ link_to(object_name(object), object.url, :id => show_id(:link, object.id),
22
22
  :class => merge_classes(:link, object.active, object.link_classes))+
23
23
  yield
24
24
  end
@@ -34,7 +34,7 @@ module SemanticNavigation
34
34
  def leaf(object)
35
35
  content_tag :li, nil, :id => show_id(:leaf, object.id),
36
36
  :class => merge_classes(:leaf, object.active, object.classes) do
37
- link_to object.name, object.url, :id => show_id(:link, object.id),
37
+ link_to object_name(object), object.url, :id => show_id(:link, object.id),
38
38
  :class => merge_classes(:link, object.active, object.link_classes)
39
39
  end
40
40
  end
@@ -29,7 +29,7 @@ module SemanticNavigation
29
29
  end
30
30
 
31
31
  module ClassMethods
32
-
32
+
33
33
  def style_accessor(hash)
34
34
  hash.keys.each do |key|
35
35
  class_eval "
@@ -66,7 +66,7 @@ module SemanticNavigation
66
66
  end
67
67
 
68
68
  module InstanceMethods
69
- attr_accessor :from_level, :until_level, :except_for
69
+ attr_accessor :from_level, :until_level, :except_for, :name
70
70
 
71
71
  def level=(level)
72
72
  @from_level = level
@@ -103,6 +103,10 @@ module SemanticNavigation
103
103
  def show_id(name, id)
104
104
  id if send("show_#{name}_id")
105
105
  end
106
+
107
+ def object_name(object)
108
+ object.name(self.name)
109
+ end
106
110
 
107
111
  end
108
112
 
@@ -33,7 +33,7 @@ module SemanticNavigation
33
33
  content_tag(:li, nil, :id => show_id(:leaf, object.id),
34
34
  :class => merge_classes(:leaf, object.active, object.classes)) do
35
35
  [object.ico ? content_tag(:i,nil,:class => "icon-#{object.ico}") : ''.html_safe,
36
- link_to(object.name, object.url, :id => show_id(:link, object.id),
36
+ link_to(object_name(object), object.url, :id => show_id(:link, object.id),
37
37
  :class => merge_classes(:link, object.active, object.link_classes)),
38
38
  content_tag(:span, nil, :class=> [:divider]) {breadcrumb_separator}].sum
39
39
  end +
@@ -45,10 +45,10 @@ module SemanticNavigation
45
45
  :class => merge_classes(:leaf, object.active, object.classes) do
46
46
  [object.ico ? content_tag(:i,nil,:class => "icon-#{object.ico}") : ''.html_safe,
47
47
  if last_as_link
48
- link_to(object.name, object.url, :id => show_id(:link, object.id),
49
- :class => merge_classes(:link, object.active, object.link_classes))
48
+ link_to(object_name(object), object.url, :id => show_id(:link, object.id),
49
+ :class => merge_classes(:link, object.active, object.link_classes))
50
50
  else
51
- object.name
51
+ object_name(object)
52
52
  end].sum
53
53
  end
54
54
  end
@@ -24,9 +24,9 @@ module SemanticNavigation
24
24
  def node(object)
25
25
  if object.ico
26
26
  name = [content_tag(:i,nil,:class => "icon-#{object.ico}"),
27
- object.name].sum
27
+ object_name(object)].sum
28
28
  else
29
- name = object.name
29
+ name = object_name(object)
30
30
  end
31
31
 
32
32
  content_tag :li, nil, :id => show_id(:leaf, object.id),
@@ -45,7 +45,7 @@ module SemanticNavigation
45
45
  end
46
46
 
47
47
  def leaf(object)
48
- if object.name.empty? && object.url.nil?
48
+ if object_name(object).empty? && object.url.nil?
49
49
  classes = 'divider'
50
50
  elsif object.url.nil?
51
51
  classes = 'nav-header'
@@ -55,9 +55,9 @@ module SemanticNavigation
55
55
 
56
56
  if object.ico
57
57
  name = [content_tag(:i,nil,:class => "icon-#{object.ico}"),
58
- object.name].sum
58
+ object_name(object)].sum
59
59
  else
60
- name = object.name
60
+ name = object_name(object)
61
61
  end
62
62
 
63
63
  content_tag :li, nil, :id => show_id(:leaf, object.id),
@@ -66,7 +66,7 @@ module SemanticNavigation
66
66
  name
67
67
  else
68
68
  link_to name, object.url, :id => show_id(:link, object.id),
69
- :class => merge_classes(:link, object.active, object.link_classes)
69
+ :class => merge_classes(:link, object.active, object.link_classes)
70
70
  end
71
71
  end
72
72
  end