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.
@@ -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,3 @@
1
+ module RocketNavigation
2
+ VERSION = "0.1.0"
3
+ 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