rocket_navigation 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +13 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +205 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +23 -0
- data/README.md +154 -0
- data/Rakefile +15 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rocket_navigation.rb +32 -0
- data/lib/rocket_navigation/configuration.rb +21 -0
- data/lib/rocket_navigation/helpers.rb +120 -0
- data/lib/rocket_navigation/item.rb +114 -0
- data/lib/rocket_navigation/item_container.rb +135 -0
- data/lib/rocket_navigation/railtie.rb +10 -0
- data/lib/rocket_navigation/renderer.rb +13 -0
- data/lib/rocket_navigation/renderer/base.rb +159 -0
- data/lib/rocket_navigation/renderer/breadcrumbs.rb +58 -0
- data/lib/rocket_navigation/renderer/breadcrumbs_on_rails.rb +27 -0
- data/lib/rocket_navigation/renderer/json.rb +29 -0
- data/lib/rocket_navigation/renderer/links.rb +35 -0
- data/lib/rocket_navigation/renderer/list.rb +45 -0
- data/lib/rocket_navigation/renderer/text.rb +21 -0
- data/lib/rocket_navigation/version.rb +3 -0
- data/rocket_navigation.gemspec +38 -0
- metadata +255 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
module RocketNavigation
|
2
|
+
class Railtie < ::Rails::Railtie
|
3
|
+
initializer 'rocket_navigation.init' do |app|
|
4
|
+
ActionController::Base.send(:include, RocketNavigation::Helpers)
|
5
|
+
RocketNavigation::Helpers.instance_methods.each do |m|
|
6
|
+
ActionController::Base.send(:helper_method, m.to_sym)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rocket_navigation/helpers'
|
2
|
+
require 'rocket_navigation/renderer/base'
|
3
|
+
|
4
|
+
module RocketNavigation
|
5
|
+
module Renderer
|
6
|
+
autoload :List, 'rocket_navigation/renderer/list'
|
7
|
+
autoload :Links, 'rocket_navigation/renderer/links'
|
8
|
+
autoload :Breadcrumbs, 'rocket_navigation/renderer/breadcrumbs'
|
9
|
+
autoload :BreadcrumbsOnRails, 'rocket_navigation/renderer/breadcrumbs_on_rails'
|
10
|
+
autoload :Text, 'rocket_navigation/renderer/text'
|
11
|
+
autoload :Json, 'rocket_navigation/renderer/json'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module RocketNavigation
|
4
|
+
module Renderer
|
5
|
+
# This is the base class for all renderers.
|
6
|
+
#
|
7
|
+
# A renderer is responsible for rendering an ItemContainer and its
|
8
|
+
# containing items to HTML.
|
9
|
+
class Base
|
10
|
+
extend Forwardable
|
11
|
+
attr_reader :container, :options
|
12
|
+
|
13
|
+
def_delegators :container, :view_context
|
14
|
+
def_delegators :view_context, :link_to, :content_tag
|
15
|
+
|
16
|
+
def initialize(container, options = {})
|
17
|
+
@container = container
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def selected_class(type)
|
22
|
+
container.selected_class[type] || options[:selected_class][type]
|
23
|
+
end
|
24
|
+
|
25
|
+
def container_html
|
26
|
+
@container_html ||= container.container_html.merge(options[:container_html] || {})
|
27
|
+
end
|
28
|
+
|
29
|
+
# override this method if needed
|
30
|
+
def container_options
|
31
|
+
container_html
|
32
|
+
end
|
33
|
+
|
34
|
+
def base_item_html
|
35
|
+
@base_item_html ||= container.item_html.merge(options[:item_html] || {})
|
36
|
+
end
|
37
|
+
|
38
|
+
def item_html(item)
|
39
|
+
classes = Array.wrap(base_item_html[:class] || [])
|
40
|
+
if item.selected?
|
41
|
+
classes.push(selected_class(:item))
|
42
|
+
end
|
43
|
+
if item.active_branch?
|
44
|
+
classes.push(selected_class(:branch))
|
45
|
+
end
|
46
|
+
|
47
|
+
base_item_html.except(:class).merge({
|
48
|
+
class: classes.reject { |c| c.nil? }
|
49
|
+
})
|
50
|
+
end
|
51
|
+
|
52
|
+
# override this method if needed
|
53
|
+
def item_options(item)
|
54
|
+
item_html(item)
|
55
|
+
end
|
56
|
+
|
57
|
+
def base_link_html
|
58
|
+
@base_link_html ||= container.link_html.merge(options[:link_html] || {})
|
59
|
+
end
|
60
|
+
|
61
|
+
def link_html(item)
|
62
|
+
classes = Array.wrap(base_link_html[:class] || [])
|
63
|
+
if item.selected?
|
64
|
+
classes.push(selected_class(:link))
|
65
|
+
end
|
66
|
+
ret = base_link_html.except(:class)
|
67
|
+
ret.merge!({
|
68
|
+
class: classes.reject { |c| c.nil? }
|
69
|
+
})
|
70
|
+
|
71
|
+
unless item.method.blank?
|
72
|
+
ret.merge!({
|
73
|
+
method: method
|
74
|
+
})
|
75
|
+
end
|
76
|
+
ret
|
77
|
+
end
|
78
|
+
|
79
|
+
# override this method if needed
|
80
|
+
def link_options(item)
|
81
|
+
link_html(item)
|
82
|
+
end
|
83
|
+
|
84
|
+
def expand_all?
|
85
|
+
!options.key?(:expand_all) || options[:expand_all] == false
|
86
|
+
end
|
87
|
+
|
88
|
+
def level
|
89
|
+
options[:level] || :all
|
90
|
+
end
|
91
|
+
|
92
|
+
def skip_if_empty?
|
93
|
+
!!options[:skip_if_empty]
|
94
|
+
end
|
95
|
+
|
96
|
+
def include_sub_navigation?(item)
|
97
|
+
consider_sub_navigation?(item) && expand_sub_navigation?(item)
|
98
|
+
end
|
99
|
+
|
100
|
+
def render_sub_navigation_for(item)
|
101
|
+
item.sub_navigation.render(options)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Renders the specified ItemContainer to HTML.
|
105
|
+
#
|
106
|
+
# When implementing a renderer, please consider to call
|
107
|
+
# include_sub_navigation? to determine whether an item's sub_navigation
|
108
|
+
# should be rendered or not.
|
109
|
+
def render(item_container)
|
110
|
+
fail NotImplementedError, 'subclass responsibility'
|
111
|
+
end
|
112
|
+
|
113
|
+
def consider_sub_navigation?(item)
|
114
|
+
return false unless item.sub_navigation
|
115
|
+
|
116
|
+
case level
|
117
|
+
when :all
|
118
|
+
true
|
119
|
+
when Range
|
120
|
+
item.sub_navigation.level <= level.max
|
121
|
+
else
|
122
|
+
false
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def expand_sub_navigation?(item)
|
127
|
+
expand_all? || item.selected?
|
128
|
+
end
|
129
|
+
|
130
|
+
# to allow overriding when there is specific logic determining
|
131
|
+
# when a link should not be rendered (eg. breadcrumbs renderer
|
132
|
+
# does not render the final breadcrumb as a link when instructed
|
133
|
+
# not to do so.)
|
134
|
+
def suppress_link?(item)
|
135
|
+
item.url.nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
# determine and return link or static content depending on
|
139
|
+
# item/renderer conditions.
|
140
|
+
def tag_for(item)
|
141
|
+
if suppress_link?(item)
|
142
|
+
suppressed_tag_for(item)
|
143
|
+
else
|
144
|
+
active_tag_for(item)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# render an item as a non-active link (span)
|
149
|
+
def suppressed_tag_for(item)
|
150
|
+
content_tag('span', item.name, link_options(item).except(:method))
|
151
|
+
end
|
152
|
+
|
153
|
+
# render an item as an active link (a)
|
154
|
+
def active_tag_for(item)
|
155
|
+
link_to(item.name, item.url, link_options(item))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RocketNavigation
|
2
|
+
module Renderer
|
3
|
+
# Renders an ItemContainer as a <div> element and its containing items as
|
4
|
+
# <a> elements.
|
5
|
+
# It only renders 'selected' elements.
|
6
|
+
#
|
7
|
+
# By default, the renderer sets the item's key as dom_id for the rendered
|
8
|
+
# <a> element unless the config option <tt>autogenerate_item_ids</tt> is
|
9
|
+
# set to false.
|
10
|
+
#
|
11
|
+
# The id can also be explicitely specified by setting the id in the
|
12
|
+
# html-options of the 'item' method in the config/navigation.rb file.
|
13
|
+
# The ItemContainer's dom_attributes are applied to the surrounding <div>
|
14
|
+
# element.
|
15
|
+
class Breadcrumbs < RocketNavigation::Renderer::Base
|
16
|
+
def render(item_container)
|
17
|
+
content = a_tags(item_container)
|
18
|
+
content_tag(
|
19
|
+
:div,
|
20
|
+
prefix_for(content) + content,
|
21
|
+
container_html
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def a_tags(item_container)
|
28
|
+
list = ActiveSupport::SafeBuffer.new
|
29
|
+
item_container.items.each do |item|
|
30
|
+
next unless item.selected?
|
31
|
+
list << tag_for(item)
|
32
|
+
|
33
|
+
if include_sub_navigation?(item)
|
34
|
+
list << join_with
|
35
|
+
list << a_tags(item.sub_navigation)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
list
|
39
|
+
end
|
40
|
+
|
41
|
+
def join_with
|
42
|
+
@join_with ||= options[:join_with] || ' '.html_safe
|
43
|
+
end
|
44
|
+
|
45
|
+
def suppress_link?(item)
|
46
|
+
super || (options[:static_leaf] && item.active_leaf?)
|
47
|
+
end
|
48
|
+
|
49
|
+
def prefix_for(content)
|
50
|
+
if !content.empty? && options[:prefix]
|
51
|
+
options[:prefix]
|
52
|
+
else
|
53
|
+
''
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RocketNavigation
|
2
|
+
module Renderer
|
3
|
+
# Renders an ItemContainer as a <div> element and its containing items as
|
4
|
+
# <a> elements.
|
5
|
+
# It only renders 'selected' elements.
|
6
|
+
#
|
7
|
+
# By default, the renderer sets the item's key as dom_id for the rendered
|
8
|
+
# <a> element unless the config option <tt>autogenerate_item_ids</tt> is
|
9
|
+
# set to false.
|
10
|
+
#
|
11
|
+
# The id can also be explicitely specified by setting the id in the
|
12
|
+
# html-options of the 'item' method in the config/navigation.rb file.
|
13
|
+
# The ItemContainer's dom_attributes are applied to the surrounding <div>
|
14
|
+
# element.
|
15
|
+
class BreadcrumbsOnRails < RocketNavigation::Renderer::Base
|
16
|
+
def render(item_container)
|
17
|
+
item_container.items.each do |item|
|
18
|
+
next unless item.selected?
|
19
|
+
add_breadcrumb(item.name, item.url, item_html(item))
|
20
|
+
if include_sub_navigation?(item)
|
21
|
+
render(item.sub_navigation)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module RocketNavigation
|
4
|
+
module Renderer
|
5
|
+
# Renders the navigation items as a object tree serialized as a json string,
|
6
|
+
# can also output raw ruby Hashes
|
7
|
+
class Json < RocketNavigation::Renderer::Base
|
8
|
+
def render(item_container)
|
9
|
+
results = hash_render(item_container)
|
10
|
+
options[:as_hash] ? results : results.to_json
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def hash_render(item_container)
|
16
|
+
return nil unless item_container
|
17
|
+
|
18
|
+
item_container.items.map do |item|
|
19
|
+
{
|
20
|
+
items: hash_render(item.sub_navigation),
|
21
|
+
name: item.name,
|
22
|
+
selected: item.selected?,
|
23
|
+
url: item.url
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RocketNavigation
|
2
|
+
module Renderer
|
3
|
+
# Renders an ItemContainer as a <div> element and its containing items as
|
4
|
+
# <a> elements.
|
5
|
+
# It adds the 'selected' class to the <a> element that is currently active.
|
6
|
+
#
|
7
|
+
# The Links renderer cannot be used to render nested navigations. If you
|
8
|
+
# would like it to use with nested navigations, you have to render each
|
9
|
+
# level separately.
|
10
|
+
#
|
11
|
+
# By default, the renderer sets the item's key as dom_id for the rendered
|
12
|
+
# <a> element unless the config option <tt>autogenerate_item_ids</tt> is set
|
13
|
+
# to false.
|
14
|
+
# The id can also be explicitely specified by setting the id in the
|
15
|
+
# html-options of the 'item' method in the config/navigation.rb file.
|
16
|
+
# The ItemContainer's dom_attributes are applied to the surrounding <div>
|
17
|
+
# element.
|
18
|
+
class Links < RocketNavigation::Renderer::Base
|
19
|
+
def render(item_container)
|
20
|
+
div_content = ActiveSupport::SafeBuffer.new
|
21
|
+
item_container.items.each_with_index do |item, index|
|
22
|
+
div_content << tag_for(item)
|
23
|
+
unless index == item_container.items.length - 1
|
24
|
+
div_content << join_with
|
25
|
+
end
|
26
|
+
end
|
27
|
+
content_tag :div, div_content, container_html
|
28
|
+
end
|
29
|
+
|
30
|
+
def join_with
|
31
|
+
@join_with ||= options[:join_with] || ''.html_safe
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RocketNavigation
|
2
|
+
module Renderer
|
3
|
+
# Renders an ItemContainer as a <ul> element and its containing items as
|
4
|
+
# <li> elements.
|
5
|
+
# It adds the 'selected' class to li element AND the link inside the li
|
6
|
+
# element that is currently active.
|
7
|
+
#
|
8
|
+
# If the sub navigation should be included (based on the level and
|
9
|
+
# expand_all options), it renders another <ul> containing the sub navigation
|
10
|
+
# inside the active <li> element.
|
11
|
+
#
|
12
|
+
# By default, the renderer sets the item's key as dom_id for the rendered
|
13
|
+
# <li> element unless the config option <tt>autogenerate_item_ids</tt> is
|
14
|
+
# set to false.
|
15
|
+
# The id can also be explicitely specified by setting the id in the
|
16
|
+
# html-options of the 'item' method in the config/navigation.rb file.
|
17
|
+
class List < RocketNavigation::Renderer::Base
|
18
|
+
def render(item_container)
|
19
|
+
if skip_if_empty? && item_container.empty?
|
20
|
+
''.html_safe
|
21
|
+
else
|
22
|
+
tag = options[:ordered] ? :ol : :ul
|
23
|
+
content = list_content(item_container)
|
24
|
+
content_tag(tag, content, container_html)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def render_item(item)
|
29
|
+
li_content = tag_for(item)
|
30
|
+
if include_sub_navigation?(item)
|
31
|
+
li_content << render_sub_navigation_for(item)
|
32
|
+
end
|
33
|
+
content_tag(:li, li_content, item_options(item))
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_content(item_container)
|
37
|
+
ret = ActiveSupport::SafeBuffer.new
|
38
|
+
item_container.items.each do |item|
|
39
|
+
ret << render_item(item)
|
40
|
+
end
|
41
|
+
ret
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RocketNavigation
|
2
|
+
module Renderer
|
3
|
+
# Renders the 'chain' of selected navigation items as simple text items,
|
4
|
+
# joined with an optional separator (similar to breadcrumbs, but without
|
5
|
+
# markup).
|
6
|
+
class Text < RocketNavigation::Renderer::Base
|
7
|
+
def render(item_container)
|
8
|
+
list(item_container).compact.join(options[:join_with] || ' ')
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def list(item_container)
|
14
|
+
item_container.items.keep_if(&:selected?).map do |item|
|
15
|
+
[item.name] +
|
16
|
+
(include_sub_navigation?(item) ? list(item.sub_navigation) : [])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "rocket_navigation/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rocket_navigation"
|
8
|
+
spec.version = RocketNavigation::VERSION
|
9
|
+
spec.authors = ["Gleb Tv"]
|
10
|
+
spec.email = ["glebtv@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{rocket_navigation is a gem for creating navigation / menu (for Rails).}
|
13
|
+
spec.description = %q{Currently alpha qualiy, use at your own risk.}
|
14
|
+
spec.homepage = "https://github.com/rs-pro/rocket_navigation"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'activesupport', '>= 5.0'
|
25
|
+
spec.add_runtime_dependency 'actionpack', '>= 5.0'
|
26
|
+
spec.add_runtime_dependency 'actionview', '>= 5.0'
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
29
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
30
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
31
|
+
spec.add_development_dependency "rspec-rails"
|
32
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.2'
|
33
|
+
spec.add_development_dependency 'capybara'
|
34
|
+
spec.add_development_dependency 'simplecov'
|
35
|
+
spec.add_development_dependency 'rdoc'
|
36
|
+
spec.add_development_dependency 'rails'
|
37
|
+
spec.add_development_dependency 'tzinfo', '>= 0'
|
38
|
+
end
|