semantic_navigation 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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