navigatrix 0.0.1 → 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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 28321e32d4430f1d16823c1a3d23121d25a1d2a3
4
- data.tar.gz: 8c466c5479a7330322bb2989a49d11621e13f81a
5
- SHA512:
6
- metadata.gz: d7c652b8c6d1e5ddbda0e997b1829307828d2951ae775a680c3407d1c2ff040e2fa444375a0e2facfddfa43d83a6092aa5d993b77a01af0007f758559accbebf
7
- data.tar.gz: 0eeb7a60fc49e5f7ce8a2e8c683bda0d10716694cb09f65a10d0dcf006310fd9f9245cddd599c87ecc9577fb994489f2c38dccb72ce705501ba979dd13c20568
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MTU0ZDk1YzY1NjgxODkwODM0YmE1NjcyYmRmMWQwNWRjYmYwNTUxZQ==
5
+ data.tar.gz: !binary |-
6
+ NWRlOTg0NDVmYWZkNTg1MGEwYmRhMTU2Y2EwNGM4Yjc2MjFkMjk3MA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MTI3M2I0MTIyYTE0ZjI0N2U4ZDA1NjhlNTJjMWU4MjBjYzg4YjU5NGU4NGM4
10
+ NWVmZmViNDY4NjgyMzRjZTk3NmU2NTAzZjk4MjkwZTE0N2FlMjU1YmI2ZDEw
11
+ NTQzMDU4YjQyZTJiMzM2YzNmMmIxYTVlMWE5ZThmZTM3ODM0ZWQ=
12
+ data.tar.gz: !binary |-
13
+ NWU0YzVjMGY3OTYxYWJkNTEyZTQ0ZDBiMWVkMzI1NmU2NmZiNWI1NmU2YWNl
14
+ MjdmMDVhMDhkNWE1NzNmOTk3ZjBhNGFhODVjZmNjOTk5MmZiMTcwNzdiOGZh
15
+ MmM2NDhmNTk4ZmEzNmM3NzhkZGRkNjYzOGMwYTc4ZThjMTg2ZmY=
data/README.md CHANGED
@@ -46,9 +46,13 @@ Assuming we're on the "/about-us" path, the resulting HTML will look like this:
46
46
  :render? => user_signed_in?
47
47
  }
48
48
  }, {
49
- :active_class => "active-nav-item",
50
- :html_attributes => {
51
- :class => "nav"
49
+ :item => {
50
+ :active_class => "active-nav-item"
51
+ },
52
+ :list => {
53
+ :html_attributes => {
54
+ :class => "nav"
55
+ }
52
56
  }
53
57
  }) %>
54
58
  ```
@@ -57,14 +61,45 @@ Assuming we're on the "/users/1" path, and a User is signed in, the resulting HT
57
61
  ```HTML
58
62
  <ul class="nav">
59
63
  <li><a href="/">Home</a></li>
60
- <li class="active-nav-item">Users</li>
64
+ <li class="active-nav-item"><a href="/users">Users</a></li>
61
65
  <li><a href="/sign_out">Sign Out</a></li>
62
66
  </ul>
63
67
  ```
64
68
  The "Users" item is active and not linked because the path "/users/1" matches the pattern `/\/users\/\d*/`. The "Home" item is linked because we are not on the path "/".
65
69
 
70
+ ## List Configuration Options
71
+ List configuration options are supplied via the `:list` option when rendering a navigation. For example,
72
+
73
+ ```Ruby
74
+ render_navigation(config, {
75
+ list: {
76
+ html_attributes: {
77
+ class: "nav"
78
+ }
79
+ }
80
+ })
81
+ ```
82
+
83
+ A list accepts the following configuration options:
84
+
85
+ ##### `:html_attributes`
86
+ HTML attributes added to an the list.
66
87
 
67
88
  ## List Item Configuration Options
89
+
90
+ List item configuration options can be supplied to all list items or a single list item. Supply options to a single list item via the navigation configuration.
91
+
92
+ ```Ruby
93
+ render_navigation({
94
+ "Home" => {
95
+ path: "/",
96
+ active_class: "home-active"
97
+ }
98
+ })
99
+ ```
100
+
101
+ The following options are supported.
102
+
68
103
  ##### `:path`
69
104
  Specifies where the navigation item should link to.
70
105
 
@@ -133,12 +168,78 @@ Results in the following HTML.
133
168
  ##### `:render?`
134
169
  Determines if the navigation item is rendered.
135
170
 
136
- ## List Configuration Options
137
- ##### `:html_attributes`
138
- HTML attributes added to an the list.
171
+ ### Supplying options to all list items
172
+ List configuration options are supplied via the `:item` option when rendering a navigation. For example,
173
+ ```Ruby
174
+ render_navigation(config, {
175
+ item: {
176
+ active_class: "active-item"
177
+ }
178
+ })
179
+ ```
180
+
181
+ Supported options are:
139
182
 
140
183
  ##### `:active_class`
141
184
  Determines which HTML class is applied to list items when the item is active.
142
185
 
143
186
  ##### `:inactive_class`
144
187
  Determines which HTML class is applied to list items when the item is *not* active.
188
+
189
+ `active_class`, `inactive_class`, `html_attributes`.
190
+
191
+ ## Building Custom List Renderers
192
+
193
+ To change the default list rendering from \<ul> tags to \<section> tags with an id of "nav", create a custom list renderer:
194
+
195
+ ```Ruby
196
+ Navigatrix.register_list_renderer(:my_custom_list) do |renderer|
197
+ renderer.wrapper do |items, html_attributes|
198
+ content_tag(:section, items, html_attributes.merge_attribute(:id, "nav"))
199
+ end
200
+ end
201
+ ```
202
+
203
+ ```ERB
204
+ <%= render_navigation({
205
+ "Home" => "/",
206
+ "About Us" => "/about-us",
207
+ }, {
208
+ list: {renderer: :my_custom_list}
209
+ }) %>
210
+ ```
211
+
212
+ ## Building Custom Item Renderers
213
+
214
+ If the basic list and and item configuration, custom renders can be registered.
215
+
216
+ For example, to add change the default item rendering from \<li> tags to \<p> tags, create a custom item renderer:
217
+
218
+ ```Ruby
219
+ Navigatrix.register_item_renderer(:my_custom_item) do |renderer|
220
+ renderer.wrapper do |content, children, html_attributes|
221
+ content(:p, content + children, html_attributes)
222
+ end
223
+ end
224
+ ```
225
+
226
+ ```ERB
227
+ <%= render_navigation({
228
+ "Home" => "/",
229
+ "About Us" => "/about-us",
230
+ }, {
231
+ item: {renderer: :my_custom_item}
232
+ }) %>
233
+ ```
234
+
235
+ #### All item rendering options
236
+
237
+ `wrapper` - wraps item content - accepts `content, children, html_attributes`
238
+
239
+ `linked` - content when the item is linked - accepts `name, path`
240
+
241
+ `unlinked` - content when the item is not linked - accepts `name, path`
242
+
243
+ `html_attributes` - HTML attributes for the item
244
+
245
+ `children_options` - attributes passed to the child list
@@ -2,8 +2,31 @@ require "navigatrix/version"
2
2
  require "navigatrix/item"
3
3
  require "navigatrix/item_collection"
4
4
  require "navigatrix/renderer"
5
+ require "navigatrix/builder"
5
6
  require 'navigatrix/integration/rails' if defined?(Rails)
6
7
  require 'navigatrix/integration/sinatra' if defined?(Sinatra)
7
8
 
8
9
  module Navigatrix
10
+ extend self
11
+
12
+ mattr_accessor :list_renderers
13
+
14
+ self.list_renderers = {
15
+ :unordered_list => Rendering::Strategies::List,
16
+ :bootstrap_navbar => Rendering::Strategies::Bootstrap::Navbar,
17
+ :bootstrap_tabs => Rendering::Strategies::Bootstrap::Tabs
18
+ }
19
+
20
+ mattr_accessor :item_renderers
21
+ self.item_renderers = {
22
+ :item => Rendering::Strategies::Item
23
+ }
24
+
25
+ def register_list_renderer(name, &block)
26
+ list_renderers[name] = ListBuilder.build(&block)
27
+ end
28
+
29
+ def register_item_renderer(name, &block)
30
+ item_renderers[name] = ItemBuilder.build(&block)
31
+ end
9
32
  end
@@ -0,0 +1,69 @@
1
+ module Navigatrix
2
+ class Builder
3
+ attr_reader :klass
4
+
5
+ def self.build(&block)
6
+ instance = new(klass)
7
+ block.call(instance)
8
+ instance.klass
9
+ end
10
+
11
+ def initialize(klass)
12
+ @klass = Class.new(klass)
13
+ end
14
+
15
+ def define_method(method_name, &block)
16
+ @klass.send(:define_method, method_name, &block)
17
+ end
18
+ end
19
+
20
+ class ListBuilder < Builder
21
+ def self.klass
22
+ Navigatrix::Rendering::Strategies::List
23
+ end
24
+
25
+ def wrapper(&block)
26
+ define_method(:render) do
27
+ instance_exec(render_items, html_attributes, &block)
28
+ end
29
+ end
30
+ end
31
+
32
+ class ItemBuilder < Builder
33
+ def self.klass
34
+ Navigatrix::Rendering::Strategies::Item
35
+ end
36
+
37
+ def wrapper(&block)
38
+ define_method(:render) do
39
+ instance_exec(name_or_link, render_children, html_attributes, &block) if render?
40
+ end
41
+ end
42
+
43
+ def linked(&block)
44
+ define_method(:linked_content) do
45
+ instance_exec(name, path, &block)
46
+ end
47
+ end
48
+
49
+ def unlinked(&block)
50
+ define_method(:unlinked_content) do
51
+ instance_exec(name, path, &block)
52
+ end
53
+ end
54
+
55
+ def children_options(&block)
56
+ define_method(:children_options) do
57
+ instance_exec(super(), &block)
58
+ end
59
+ end
60
+
61
+ def html_attributes(&block)
62
+ define_method(:html_attributes) do
63
+ instance_exec(&block).inject(super()) do |acc, (key, val)|
64
+ acc.merge_attribute(key, val)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -23,6 +23,14 @@ module Navigatrix
23
23
  {}
24
24
  end
25
25
 
26
+ def active_class
27
+ nil
28
+ end
29
+
30
+ def inactive_class
31
+ nil
32
+ end
33
+
26
34
  def render?
27
35
  true
28
36
  end
@@ -30,6 +38,8 @@ module Navigatrix
30
38
 
31
39
  class AdvancedConfig < OpenStruct
32
40
  DEFAULTS = {
41
+ :active_class => nil,
42
+ :inactive_class => nil,
33
43
  :html_attributes => {},
34
44
  :render? => true,
35
45
  :children => {}
@@ -6,7 +6,7 @@ module Navigatrix
6
6
  class Item < Struct.new(:name, :config, :context)
7
7
  extend Forwardable
8
8
  delegate :current_path => :context
9
- delegate [:render?, :html_attributes] => :config
9
+ delegate [:render?, :html_attributes, :active_class, :inactive_class] => :config
10
10
 
11
11
  def active?
12
12
  applicable_active_state? ||
@@ -1,4 +1,5 @@
1
1
  require "navigatrix/rendering/context"
2
+ require "navigatrix/rendering/strategy_factory"
2
3
  require "navigatrix/rendering/strategies/list"
3
4
  require "navigatrix/rendering/strategies/bootstrap/navbar"
4
5
  require "navigatrix/rendering/strategies/bootstrap/tabs"
@@ -7,23 +8,14 @@ module Navigatrix
7
8
  class Renderer
8
9
  attr_reader :configuration, :strategy, :render_context, :render_options
9
10
 
10
- REGISTERED_STRATEGIES = {
11
- :unordered_list => Rendering::Strategies::List,
12
- :bootstrap_navbar => Rendering::Strategies::Bootstrap::Navbar,
13
- :bootstrap_tabs => Rendering::Strategies::Bootstrap::Tabs
14
- }
15
-
16
- class MissingStrategy < NameError ; end
17
-
18
11
  def initialize(configuration, options)
19
12
  @configuration = configuration
20
- @strategy = find_strategy(options.delete(:strategy))
21
13
  @render_context = Rendering::Context.new(options.delete(:render_context))
22
14
  @render_options = options
23
15
  end
24
16
 
25
17
  def render
26
- strategy.new(item_collection.items, render_options).render
18
+ strategy.new(item_collection.items, list_options, item_options).render
27
19
  end
28
20
 
29
21
  private
@@ -32,10 +24,24 @@ module Navigatrix
32
24
  ItemCollection.new(configuration, render_context)
33
25
  end
34
26
 
35
- def find_strategy(strategy_or_name)
36
- return strategy_or_name if strategy_or_name.is_a?(Class)
37
- strategy_or_name ||= :unordered_list
38
- REGISTERED_STRATEGIES[strategy_or_name] || raise(MissingStrategy, "can't find strategy #{strategy_name}")
27
+ def strategy
28
+ Rendering::StrategyFactory.find_list_strategy(strategy_name)
29
+ end
30
+
31
+ def strategy_name
32
+ render_options.fetch(:list, {})[:renderer]
33
+ end
34
+
35
+ def list_options
36
+ base = render_options[:html_attributes]
37
+ (base ? {html_attributes: base} : {})
38
+ .merge(render_options.fetch(:list, {}))
39
+ end
40
+
41
+ def item_options
42
+ render_options
43
+ .slice(:active_class, :inactive_class)
44
+ .merge(render_options.fetch(:item, {}))
39
45
  end
40
46
  end
41
47
  end
@@ -1,36 +1,40 @@
1
1
  require "navigatrix/rendering/strategies/list"
2
2
 
3
- module Navigatrix::Rendering::Strategies
4
- module Bootstrap
5
- class Navbar < List
3
+ module Navigatrix
4
+ module Rendering
5
+ module Strategies
6
+ module Bootstrap
7
+ class Navbar < List
6
8
 
7
- private
9
+ private
8
10
 
9
- def html_attributes
10
- super.merge_attribute(:class, "nav")
11
- end
11
+ def html_attributes
12
+ super.merge_attribute(:class, "nav")
13
+ end
12
14
 
13
- def items
14
- super.map { |item| (item.has_children? ? Item : List::Item).new(item, options) }
15
- end
15
+ def items
16
+ super.map { |item| (item.has_children? ? Item : Strategies::Item).new(item, options) }
17
+ end
16
18
 
17
- class Item < List::Item
18
- private
19
+ class Item < Strategies::Item
20
+ private
19
21
 
20
- def html_attributes
21
- super.merge_attribute(:class, "dropdown")
22
- end
22
+ def html_attributes
23
+ super.merge_attribute(:class, "dropdown")
24
+ end
23
25
 
24
- def name
25
- (super + dropdown_icon).html_safe
26
- end
26
+ def name
27
+ (super + dropdown_icon).html_safe
28
+ end
27
29
 
28
- def nested_list
29
- List.new(children, options).render if has_children?
30
- end
30
+ def nested_list
31
+ List.new(children, options).render if has_children?
32
+ end
31
33
 
32
- def dropdown_icon
33
- options[:dropdown_icon] || content_tag(:i, nil, :class => "icon-chevron-down icon-white")
34
+ def dropdown_icon
35
+ options[:dropdown_icon] || content_tag(:i, nil, :class => "icon-chevron-down icon-white")
36
+ end
37
+ end
34
38
  end
35
39
  end
36
40
  end
@@ -1,11 +1,15 @@
1
- module Navigatrix::Rendering::Strategies
2
- module Bootstrap
3
- class Tabs < List
1
+ module Navigatrix
2
+ module Rendering
3
+ module Strategies
4
+ module Bootstrap
5
+ class Tabs < List
4
6
 
5
- private
7
+ private
6
8
 
7
- def html_attributes
8
- super.merge_attribute(:class, "nav nav-tabs")
9
+ def html_attributes
10
+ super.merge_attribute(:class, "nav nav-tabs")
11
+ end
12
+ end
9
13
  end
10
14
  end
11
15
  end