semantic_navigation 0.0.6 → 0.0.8

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 (37) hide show
  1. data/Changelog.md +10 -1
  2. data/README.md +33 -4
  3. data/Rakefile +3 -0
  4. data/lib/generators/semantic_navigation/install/install_generator.rb +20 -0
  5. data/lib/generators/semantic_navigation/install/templates/semantic_navigation.en.yml +2 -0
  6. data/lib/generators/semantic_navigation/install/templates/semantic_navigation.rb +25 -0
  7. data/lib/semantic_navigation.rb +2 -0
  8. data/lib/semantic_navigation/configuration.rb +52 -44
  9. data/lib/semantic_navigation/core.rb +4 -0
  10. data/lib/semantic_navigation/core/base.rb +21 -0
  11. data/lib/semantic_navigation/core/leaf.rb +25 -0
  12. data/lib/semantic_navigation/core/navigation.rb +35 -0
  13. data/lib/semantic_navigation/core/node.rb +29 -0
  14. data/lib/semantic_navigation/helper_methods.rb +14 -17
  15. data/lib/semantic_navigation/railtie.rb +14 -6
  16. data/lib/semantic_navigation/renderers.rb +8 -0
  17. data/lib/semantic_navigation/renderers/acts_as_breadcrumb.rb +39 -0
  18. data/lib/semantic_navigation/renderers/acts_as_list.rb +46 -0
  19. data/lib/semantic_navigation/renderers/bread_crumb.rb +50 -0
  20. data/lib/semantic_navigation/renderers/list.rb +44 -0
  21. data/lib/semantic_navigation/renderers/render_helpers.rb +113 -0
  22. data/lib/semantic_navigation/twitter_bootstrap/breadcrumb.rb +58 -0
  23. data/lib/semantic_navigation/twitter_bootstrap/list.rb +76 -0
  24. data/lib/semantic_navigation/twitter_bootstrap/tabs.rb +70 -0
  25. data/lib/semantic_navigation/version.rb +1 -1
  26. data/semantic_navigation.gemspec +3 -3
  27. data/spec/lib/semantic_navigation/configuration_spec.rb +55 -0
  28. data/spec/lib/semantic_navigation/custom_renderer.rb +3 -0
  29. data/spec/lib/semantic_navigation/helper_methods_spec.rb +1 -0
  30. data/spec/lib/semantic_navigation_spec.rb +1 -0
  31. data/spec/spec_helper.rb +8 -0
  32. metadata +32 -14
  33. data/lib/semantic_navigation/core/procs.rb +0 -15
  34. data/lib/semantic_navigation/core/render.rb +0 -94
  35. data/lib/semantic_navigation/item.rb +0 -118
  36. data/lib/tasks/semantic_navigation.rake +0 -8
  37. data/lib/tasks/templates/semantic_navigation.rb +0 -53
@@ -1,4 +1,13 @@
1
- ### 0.0.6 /February 10th, 2012
1
+ ### 0.0.8 /
2
+
3
+ * New configuration logic
4
+ * New helper render method
5
+ * Reloadable in development, and caching in production
6
+ * I18n support
7
+ * Render config, can be set through helper render method
8
+ * Included support for custom renderers
9
+
10
+ ### 0.0.6 / February 10th, 2012
2
11
 
3
12
  * Now uses fileutils raver ftools for ruby-1.9.x
4
13
  * Some fixes for ruby-1.9.x
data/README.md CHANGED
@@ -1,9 +1,15 @@
1
1
  This is semantic_navigation
2
2
 
3
- Current version: 0.1.0
3
+ Current version: 0.0.8
4
4
 
5
5
  ###Purpose
6
- The purpose of this gem is to generate simple and usefull navigation. You can define different menus and render them separately, specify root nodes, setup your own renderers and other.
6
+ This gem generates the navigation for your Rails app.
7
+ Really customizable and simple to use.
8
+ Using this gem you have 4 types of renderers: menu, breadcrumb, tabs, and, pills
9
+
10
+ You can define different menus and render them separatelly.
11
+
12
+ Now with simple integration with a twitter-bootstrap css framework.
7
13
 
8
14
  ###How to install
9
15
 
@@ -19,7 +25,30 @@ $ bundle install
19
25
 
20
26
  Generate the config file:
21
27
  <pre><code>
22
- $ rake semantic_navigation:install
28
+ $ rails generate semantic_navigation:install
23
29
  </code></pre>
24
30
 
25
- For the information of how to configure and render your menus read the <a href='https://github.com/fr33z3/semantic_navigation/wiki'>Wiki</a>
31
+ ###Quick start
32
+
33
+ Configure your navigation in config/semantic_navigation.rb
34
+
35
+ <pre><code>
36
+ SemanticNavigation::Configuration.run do
37
+ navigate :root_menu do
38
+ item :header_item, nil, :name => 'Header'
39
+ item :first_item, '#', :name => 'First Item', :ico => :tag
40
+ item :divide
41
+ item :second_item, '#', :name => 'Second Item', :ico => :user
42
+ end
43
+ end
44
+ </code></pre>
45
+
46
+ And try to render it in your layout(code in haml):
47
+ <pre><code>
48
+ .well
49
+ = navigation_for :root_menu, :as => :bootstrap_list
50
+ </code></pre>
51
+
52
+ Render the navigation using the semantic_navigation helper methods and options for them.
53
+
54
+ For the information of how to configure and render your navigation read the <a href='https://github.com/fr33z3/semantic_navigation/wiki'>Wiki</a>
data/Rakefile CHANGED
@@ -1 +1,4 @@
1
+ require 'rspec/core/rake_task'
1
2
  require "bundler/gem_tasks"
3
+
4
+ RSpec::Core::RakeTask.new('spec')
@@ -0,0 +1,20 @@
1
+ module SemanticNavigation
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+ desc "This generator creates config file for your navigation"
6
+
7
+ def add_semantic_navigation
8
+ puts <<-EOM
9
+ +===============================================================+
10
+ | SemanticNavigation install |
11
+ | Please read the Wiki to learn how to define your navigation. |
12
+ | http://github.com/fr33z3/semantic_navigation/wiki. |
13
+ +===============================================================+
14
+ EOM
15
+ copy_file "semantic_navigation.rb", "config/semantic_navigation.rb"
16
+ copy_file "semantic_navigation.en.yml", "config/locales/semantic_navigation.en.yml"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ SemanticNavigation::Configuration.run do
2
+ # Read wiki https://github.com/fr33z3/semantic_navigation/wiki to lear about
3
+ # semantic_navigation configuration
4
+
5
+ #styles_for :list do
6
+ # show_navigation_active_class true
7
+ # navigation_active_class [:some_active_class]
8
+ #end
9
+
10
+ #register_renderer :some_renderer, SomeRendererClass
11
+
12
+ #navigate :navigation do
13
+ # item :header_item, :name => 'Header Item'
14
+ # item :first_item, :first_item_route, :ico => 'user' do
15
+ # item :sub_item, :sub_item_route do
16
+ # item :sub_sub_item, :sub_sub_item_route
17
+ # end
18
+ # item :second_sub, :second_sub_route, :ico => 'user'
19
+ # end
20
+ # item :divide
21
+ # item :second_item, :second_item_route
22
+ #end
23
+
24
+ end
25
+
@@ -1,4 +1,6 @@
1
1
  require "semantic_navigation/version"
2
+ require 'semantic_navigation/core'
3
+ require 'semantic_navigation/renderers'
2
4
  require "semantic_navigation/configuration"
3
5
  require 'semantic_navigation/railtie' if defined?(Rails)
4
6
 
@@ -1,55 +1,63 @@
1
- require 'semantic_navigation/item'
2
-
3
1
  module SemanticNavigation
4
2
  class Configuration
5
3
 
6
- def self.run
7
- instance = self.new
8
- yield instance if block_given?
9
- instance
4
+ @@navigations = {}
5
+ @@renderers = {:list => Renderers::List,
6
+ :breadcrumb => Renderers::BreadCrumb,
7
+ :bootstrap_breadcrumb => TwitterBootstrap::Breadcrumb,
8
+ :bootstrap_list => TwitterBootstrap::List,
9
+ :bootstrap_tabs => TwitterBootstrap::Tabs,
10
+ :bootstrap_pills => TwitterBootstrap::Tabs
11
+ }
12
+ @@render_styles = {:bootstrap_pills => proc {
13
+ navigation_default_classes [:nav, 'nav-pills']
14
+ }
15
+ }
16
+
17
+ def self.run(&block)
18
+ self.class_eval &block if block_given?
10
19
  end
11
-
12
- def initialize
13
- @menus = {}
20
+
21
+ def self.navigate(id, options = {}, &block)
22
+ options[:id] = id.to_sym
23
+ options[:i18n_name] = "semantic_navigation.#{id}"
24
+ navigation = Core::Navigation.new(options)
25
+ navigation.instance_eval &block if block_given?
26
+ @@navigations[id.to_sym] = navigation
14
27
  end
15
-
16
- def method_missing(name, *args)
17
- name = name.to_s
18
- if name.chomp('=') != name
19
- SemanticNavigation::Item.set_default_option(name.chop,args[0])
20
- else
21
- menu = Item.new(name, args, nil)
22
- menu.level = 0
23
- @menus.merge!({name.to_sym => menu})
24
- yield menu if block_given?
28
+
29
+ def render(menu_id, renderer_name, options, view_object)
30
+ renderer = @@renderers[renderer_name].new(view_object)
31
+ unless @@render_styles[renderer_name].nil?
32
+ renderer.instance_eval &@@render_styles[renderer_name]
25
33
  end
34
+ options.keys.each{|key| renderer.send "#{key}=", options[key]}
35
+ navigation = @@navigations[menu_id]
36
+ navigation.mark_active(view_object)
37
+ navigation.render(renderer)
26
38
  end
27
-
28
- def render(name, command = :render)
29
- if @menus[name.to_sym]
30
- if command == :render
31
- return @menus[name.to_sym].render
32
- elsif command == :active_item_name
33
- item = @menus[name.to_sym].find_active_item
34
- !item.nil? ? item.name : ''
35
- elsif command == :active_item_parent_name
36
- item = @menus[name.to_sym].find_active_item
37
- !item.nil? && !item.parent.nil? ? item.parent.name : ''
38
- elsif command == :breadcrumb
39
- return @menus[name.to_sym].render_breadcrumb
40
- elsif command == :root
41
- return @menus[name.to_sym].render_levels 1
42
- elsif command.is_a?(Hash) && command.keys == [:levels]
43
- return @menus[name.to_sym].render_levels command[:levels]
44
- elsif command.is_a?(Hash) && command.keys == [:from_level]
45
- return @menus[name.to_sym].render_from command[:from_level]
46
- else
47
- raise NoMethodError.new("Wrong menu render parameter:`#{command.to_s}`")
48
- end
49
- else
50
- raise NoMethodError.new("No such menu name:`#{name}` check your #{Rails.root}/config/semantic_navigation.rb file")
39
+
40
+ def self.styles_for(name)
41
+ @@render_styles[name.to_sym] = proc
42
+ end
43
+
44
+ def self.to_s
45
+ "<#{self.name}:#{@@navigations};#{@@renderers}>"
46
+ end
47
+
48
+ def self.register_renderer(*options)
49
+ if options.count == 1
50
+ name = options[0].name.demodulize.underscore.to_sym
51
+ @@renderers[name] = options[0]
52
+ elsif options.count == 2
53
+ name = options[0].to_sym
54
+ @@renderers[name] = options[1]
51
55
  end
52
56
  end
53
-
57
+
58
+ def navigation(name)
59
+ @@navigations[name]
60
+ end
61
+
54
62
  end
55
63
  end
@@ -0,0 +1,4 @@
1
+ require 'semantic_navigation/core/base'
2
+ require 'semantic_navigation/core/navigation'
3
+ require 'semantic_navigation/core/leaf'
4
+ require 'semantic_navigation/core/node'
@@ -0,0 +1,21 @@
1
+ module SemanticNavigation
2
+ module Core
3
+ class Base
4
+
5
+ attr :id, :level, :classes, :active
6
+
7
+ def initialize(options, level)
8
+ @level = level
9
+ options.keys.each do |option_name|
10
+ instance_variable_set :"@#{option_name}", options[option_name]
11
+ end
12
+ end
13
+
14
+ def render(renderer)
15
+ class_name = self.class.name.split('::').last.downcase
16
+ renderer.send :"render_#{class_name}", self
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ module SemanticNavigation
2
+ module Core
3
+ class Leaf < Base
4
+ attr :url, :link_classes
5
+
6
+ def initialize(options, level)
7
+ super options, level
8
+ end
9
+
10
+ def name
11
+ rendering_name = @name || I18n.t("#{@i18n_name}.#{@id}", :default => '')
12
+ rendering_name.is_a?(Proc) ? rendering_name.call.to_s : rendering_name
13
+ end
14
+
15
+ def mark_active(view_object)
16
+ if @url
17
+ @active = view_object.current_page?(@url)
18
+ else
19
+ @active = false
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ module SemanticNavigation
2
+ module Core
3
+ class Navigation < Base
4
+ attr :sub_elements
5
+
6
+ def initialize(options, level = 0)
7
+ @sub_elements = []
8
+ super options, level
9
+ end
10
+
11
+ def item(id, url=nil, options={}, &block)
12
+ options[:id] = id.to_sym
13
+ options[:url] = url unless url.nil?
14
+ options[:i18n_name] = @i18n_name
15
+
16
+ if block_given?
17
+ element = Node.new(options, @level+1)
18
+ element.instance_eval &block
19
+ else
20
+ element = Leaf.new(options, @level+1)
21
+ end
22
+
23
+ @sub_elements.push element
24
+ end
25
+
26
+ def mark_active(view_object)
27
+ @sub_elements.each do |element|
28
+ element.mark_active(view_object)
29
+ end
30
+ @active = !@sub_elements.find{|element| element.active}.nil?
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module SemanticNavigation
2
+ module Core
3
+ class Node < Navigation
4
+ attr :url, :link_classes, :node_classes
5
+
6
+ def initialize(options, level)
7
+ super options, level
8
+ end
9
+
10
+ def name
11
+ rendering_name = @name || i18n_name
12
+ rendering_name.is_a?(Proc) ? rendering_name.call.to_s : rendering_name
13
+ end
14
+
15
+ def mark_active(view_object)
16
+ @sub_elements.each{|element| element.mark_active(view_object)}
17
+ @active = view_object.current_page?(@url)
18
+ @active |= !@sub_elements.find{|element| element.active}.nil?
19
+ end
20
+
21
+ private
22
+
23
+ def i18n_name
24
+ I18n.t("#{@i18n_name}.#{@id}", :default => '')
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -1,23 +1,20 @@
1
1
  module SemanticNavigation::HelperMethods
2
-
3
- def method_missing(name, command = :render)
4
- name = name.to_s
5
- if name[0..6] == 'render_'
6
- SemanticNavigation::Item.set_default_option('view_object',self)
7
- semantic_navigation_config.render(name[7..-1], command)
8
- else
9
- raise NoMethodError.new("NoMethodError:#{name}")
10
- end
11
- end
12
2
 
13
- private
14
-
15
- def semantic_navigation_config
16
- if @__semantic_navigation_config.nil?
17
- @__semantic_navigation_config = eval(IO.read("#{Rails.root}/config/semantic_navigation.rb"))
3
+ def navigation_for(name, options = {})
4
+ render_name = options.delete :as
5
+ render_name ||= :list
6
+ SemanticNavigation::Configuration.new.render(name, render_name, options, self)
7
+ end
8
+
9
+ def active_item_for(name, level = nil)
10
+ navigation = SemanticNavigation::Configuration.new.navigation(name)
11
+ item = navigation
12
+ while !item.is_a?(SemanticNavigation::Core::Leaf) &&
13
+ !item.sub_elements.find{|e| e.active}.nil? &&
14
+ (!level.nil? ? item.level < level : true)
15
+ item = item.sub_elements.find{|e| e.active}
18
16
  end
19
- @__semantic_navigation_config
17
+ item.name if item != navigation
20
18
  end
21
-
22
19
 
23
20
  end
@@ -2,14 +2,22 @@ require 'semantic_navigation/helper_methods'
2
2
 
3
3
  module SemanticNavigation
4
4
  class Railtie < Rails::Railtie
5
-
6
- initializer "semantic_navigation.helper_methods" do
7
- ActionView::Base.send :include, HelperMethods
5
+
6
+ initializer "semantic_navigation.extend_helper_methods" do
7
+ ActiveSupport.on_load :action_view do
8
+ ActionView::Base.send :include, HelperMethods
9
+ end
8
10
  end
9
11
 
10
- rake_tasks do
11
- Dir[File.join(File.dirname(__FILE__),'../tasks/*.rake')].each {|f| load f}
12
+ if Rails.env == "production"
13
+ config.after_initialize {
14
+ load "#{Rails.root}/config/semantic_navigation.rb"
15
+ }
16
+ else
17
+ ActionDispatch::Callbacks.before {
18
+ load "#{Rails.root}/config/semantic_navigation.rb"
19
+ }
12
20
  end
13
-
21
+
14
22
  end
15
23
  end
@@ -0,0 +1,8 @@
1
+ require 'semantic_navigation/renderers/render_helpers'
2
+ require 'semantic_navigation/renderers/acts_as_list'
3
+ require 'semantic_navigation/renderers/acts_as_breadcrumb'
4
+ require 'semantic_navigation/renderers/list'
5
+ require 'semantic_navigation/renderers/bread_crumb'
6
+ require 'semantic_navigation/twitter_bootstrap/breadcrumb'
7
+ require 'semantic_navigation/twitter_bootstrap/list'
8
+ require 'semantic_navigation/twitter_bootstrap/tabs'
@@ -0,0 +1,39 @@
1
+ module SemanticNavigation
2
+ module Renderers
3
+ module ActsAsBreadcrumb
4
+
5
+ def render_navigation(object)
6
+ navigation(object) do
7
+ while !object.class.in?(SemanticNavigation::Core::Leaf, NilClass) &&
8
+ from_level.to_i > object.level
9
+ object = object.sub_elements.find(&:active)
10
+ end
11
+ unless object.class.in?(SemanticNavigation::Core::Leaf, NilClass)
12
+ active_element = object.sub_elements.find{|e| e.active}
13
+ active_element.render(self) if active_element
14
+ end
15
+ end
16
+ end
17
+
18
+ def render_node(object)
19
+ active_element = object.sub_elements.find{|e| e.active}
20
+ render_element = active_element.render(self) if active_element
21
+ if render_element
22
+ node(object) do
23
+ render_element
24
+ end
25
+ else
26
+ render_leaf(object)
27
+ end
28
+ end
29
+
30
+ def render_leaf(object)
31
+ show = !until_level.nil? ? object.level <= until_level+1 : true
32
+ return nil unless show
33
+
34
+ leaf(object)
35
+ end
36
+
37
+ end
38
+ end
39
+ end