simple-navigation 3.0.0.beta2 → 3.0.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.
- data/CHANGELOG +5 -0
- data/lib/simple_navigation/core/configuration.rb +2 -2
- data/lib/simple_navigation/core/item_adapter.rb +19 -1
- data/lib/simple_navigation/core/item_container.rb +2 -2
- data/lib/simple_navigation/rendering/renderer/list.rb +20 -4
- data/spec/lib/simple_navigation/core/item_adapter_spec.rb +108 -1
- data/spec/lib/simple_navigation/rendering/renderer/list_spec.rb +73 -13
- data/spec/spec_helper.rb +1 -1
- metadata +3 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
*3.0.0
|
2
|
+
|
3
|
+
* added ability to specify dynamic items using an array of hashes. Credits to Anshul Khandelwal for input and discussion.
|
4
|
+
* added ability to specify attributes for the generated link-tag in list renderer (up to now the attributes have been applied to the li-tag). Credits to Anthony Navarre for input and discussion.
|
5
|
+
|
1
6
|
*3.0.0.beta2
|
2
7
|
|
3
8
|
* moving code for initializing plugin in sinatra to separate gem
|
@@ -35,9 +35,9 @@ module SimpleNavigation
|
|
35
35
|
# This is the main method for specifying the navigation items. It can be used in two ways:
|
36
36
|
#
|
37
37
|
# 1. Declaratively specify your items in the config/navigation.rb file using a block. It then yields an SimpleNavigation::ItemContainer for adding navigation items.
|
38
|
-
# 1. Directly provide your items to the method (e.g. when loading your items from the database).
|
38
|
+
# 1. Directly provide your items to the method (e.g. when loading your items from the database).
|
39
39
|
#
|
40
|
-
# ==== Example for block style
|
40
|
+
# ==== Example for block style (configuration file)
|
41
41
|
# config.items do |primary|
|
42
42
|
# primary.item :my_item, 'My item', my_item_path
|
43
43
|
# ...
|
@@ -14,6 +14,9 @@ module SimpleNavigation
|
|
14
14
|
# * <tt>options</tt>
|
15
15
|
# * <tt>items</tt> - if one of your items has a subnavigation it must respond to <tt>items</tt> providing the subnavigation.
|
16
16
|
#
|
17
|
+
# You can also specify your items as a list of hashes. The hashes will be converted to objects automatically.
|
18
|
+
# The hashes representing the items obviously must have the keys :key, :name and :url and optionally the keys :options and :items.
|
19
|
+
#
|
17
20
|
# See SimpleNavigation::ItemContainer#item for the purpose of these methods.
|
18
21
|
class ItemAdapter
|
19
22
|
extend Forwardable
|
@@ -23,7 +26,7 @@ module SimpleNavigation
|
|
23
26
|
attr_reader :item
|
24
27
|
|
25
28
|
def initialize(item)
|
26
|
-
@item = item
|
29
|
+
@item = item.instance_of?(Hash) ? to_object(item) : item
|
27
30
|
end
|
28
31
|
|
29
32
|
# Returns the options for this item. If the wrapped item does not implement an options method, an empty hash is returned.
|
@@ -41,5 +44,20 @@ module SimpleNavigation
|
|
41
44
|
SimpleNavigation::Item.new(item_container, key, name, url, options, items)
|
42
45
|
end
|
43
46
|
|
47
|
+
protected
|
48
|
+
|
49
|
+
# Converts the specified hash into an object. Each key will be added as method.
|
50
|
+
#
|
51
|
+
def to_object(hash)
|
52
|
+
mod = Module.new do
|
53
|
+
hash.each_pair do |key, value|
|
54
|
+
define_method key do
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
Object.new.extend(mod)
|
60
|
+
end
|
61
|
+
|
44
62
|
end
|
45
63
|
end
|
@@ -71,7 +71,7 @@ module SimpleNavigation
|
|
71
71
|
#
|
72
72
|
# The options are the same as in the view's render_navigation call (they get passed on)
|
73
73
|
def render(options={})
|
74
|
-
|
74
|
+
renderer_instance = if options[:renderer]
|
75
75
|
if options[:renderer].instance_of?(Symbol) && SimpleNavigation.registered_renderers.key?(options[:renderer])
|
76
76
|
SimpleNavigation.registered_renderers[options[:renderer]].new(options)
|
77
77
|
else
|
@@ -80,7 +80,7 @@ module SimpleNavigation
|
|
80
80
|
else
|
81
81
|
self.renderer.new(options)
|
82
82
|
end
|
83
|
-
|
83
|
+
renderer_instance.render(self)
|
84
84
|
end
|
85
85
|
|
86
86
|
# Returns true if any of this container's items is selected.
|
@@ -12,12 +12,12 @@ module SimpleNavigation
|
|
12
12
|
|
13
13
|
def render(item_container)
|
14
14
|
list_content = item_container.items.inject([]) do |list, item|
|
15
|
-
|
16
|
-
li_content = link_to(item.name, item.url,
|
15
|
+
li_options = item.html_options.reject {|k, v| k == :link}
|
16
|
+
li_content = link_to(item.name, item.url, link_options_for(item))
|
17
17
|
if include_sub_navigation?(item)
|
18
18
|
li_content << render_sub_navigation_for(item)
|
19
19
|
end
|
20
|
-
list << content_tag(:li, li_content,
|
20
|
+
list << content_tag(:li, li_content, li_options)
|
21
21
|
end.join
|
22
22
|
if skip_if_empty? && item_container.empty?
|
23
23
|
''
|
@@ -25,7 +25,23 @@ module SimpleNavigation
|
|
25
25
|
content_tag(:ul, list_content, {:id => item_container.dom_id, :class => item_container.dom_class})
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
# Extracts the options relevant for the generated link
|
32
|
+
#
|
33
|
+
def link_options_for(item)
|
34
|
+
special_options = {:method => item.method, :class => item.selected_class}.reject {|k, v| v.nil? }
|
35
|
+
link_options = item.html_options[:link]
|
36
|
+
return special_options unless link_options
|
37
|
+
opts = special_options.merge(link_options)
|
38
|
+
opts[:class] = [link_options[:class], item.selected_class].flatten.compact.join(' ')
|
39
|
+
opts.delete(:class) if opts[:class].nil? || opts[:class] == ''
|
40
|
+
opts
|
41
|
+
end
|
42
|
+
|
43
|
+
|
28
44
|
end
|
29
|
-
|
45
|
+
|
30
46
|
end
|
31
47
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
2
|
|
3
|
-
describe SimpleNavigation::ItemAdapter do
|
3
|
+
describe SimpleNavigation::ItemAdapter, 'when item is an object' do
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
@item = stub(:item)
|
@@ -99,4 +99,111 @@ describe SimpleNavigation::ItemAdapter do
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
+
end
|
103
|
+
|
104
|
+
describe SimpleNavigation::ItemAdapter, 'when item is a hash' do
|
105
|
+
|
106
|
+
before(:each) do
|
107
|
+
@item = {:key => 'key', :url => 'url', :name => 'name'}
|
108
|
+
@item_adapter = SimpleNavigation::ItemAdapter.new(@item)
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'key' do
|
112
|
+
it "should delegate key to item" do
|
113
|
+
@item_adapter.item.should_receive(:key)
|
114
|
+
@item_adapter.key
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'url' do
|
119
|
+
it "should delegate url to item" do
|
120
|
+
@item_adapter.item.should_receive(:url)
|
121
|
+
@item_adapter.url
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'name' do
|
126
|
+
it "should delegate name to item" do
|
127
|
+
@item_adapter.item.should_receive(:name)
|
128
|
+
@item_adapter.name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe 'initialize' do
|
133
|
+
it "should set the item" do
|
134
|
+
@item_adapter.item.should_not be_nil
|
135
|
+
end
|
136
|
+
it "should have converted the item into an object" do
|
137
|
+
@item_adapter.item.should respond_to(:url)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'options' do
|
142
|
+
context 'item does respond to options' do
|
143
|
+
before(:each) do
|
144
|
+
@item = {:key => 'key', :url => 'url', :name => 'name', :options => {:my => :options}}
|
145
|
+
@item_adapter = SimpleNavigation::ItemAdapter.new(@item)
|
146
|
+
end
|
147
|
+
it "should return the item's options'" do
|
148
|
+
@item_adapter.options.should == {:my => :options}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
context 'item does not respond to options' do
|
152
|
+
it "should return an empty hash" do
|
153
|
+
@item_adapter.options.should == {}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe 'items' do
|
159
|
+
context 'item does respond to items' do
|
160
|
+
context 'items is nil' do
|
161
|
+
before(:each) do
|
162
|
+
@item = {:key => 'key', :url => 'url', :name => 'name', :items => nil}
|
163
|
+
@item_adapter = SimpleNavigation::ItemAdapter.new(@item)
|
164
|
+
end
|
165
|
+
it "should return nil" do
|
166
|
+
@item_adapter.items.should be_nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
context 'items is not nil' do
|
170
|
+
context 'items is empty' do
|
171
|
+
before(:each) do
|
172
|
+
@item = {:key => 'key', :url => 'url', :name => 'name', :items => []}
|
173
|
+
@item_adapter = SimpleNavigation::ItemAdapter.new(@item)
|
174
|
+
end
|
175
|
+
it "should return nil" do
|
176
|
+
@item_adapter.items.should be_nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
context 'items is not empty' do
|
180
|
+
before(:each) do
|
181
|
+
@item = {:key => 'key', :url => 'url', :name => 'name', :items => ['not', 'empty']}
|
182
|
+
@item_adapter = SimpleNavigation::ItemAdapter.new(@item)
|
183
|
+
end
|
184
|
+
it "should return the items" do
|
185
|
+
@item_adapter.items.should == ['not', 'empty']
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
context 'item does not respond to items' do
|
191
|
+
it "should return nil" do
|
192
|
+
@item_adapter.items.should be_nil
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe 'to_simple_navigation_item' do
|
198
|
+
before(:each) do
|
199
|
+
@container = stub(:container)
|
200
|
+
@item = {:key => 'key', :url => 'url', :name => 'name', :items => [], :options => {}}
|
201
|
+
@item_adapter = SimpleNavigation::ItemAdapter.new(@item)
|
202
|
+
end
|
203
|
+
it "should create a SimpleNavigation::Item" do
|
204
|
+
SimpleNavigation::Item.should_receive(:new).with(@container, 'key', 'name', 'url', {}, nil)
|
205
|
+
@item_adapter.to_simple_navigation_item(@container)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
102
209
|
end
|
@@ -29,19 +29,38 @@ describe SimpleNavigation::Renderer::List do
|
|
29
29
|
it "should render an a-tag inside each li-tag" do
|
30
30
|
HTML::Selector.new('li a').select(render).should have(3).entries
|
31
31
|
end
|
32
|
-
it "should pass the specified html_options to the li element" do
|
33
|
-
HTML::Selector.new('li[style=float:right]').select(render).should have(1).entries
|
34
|
-
end
|
35
|
-
it "should give the li the id specified in the html_options" do
|
36
|
-
HTML::Selector.new('li#my_id').select(render).should have(1).entries
|
37
|
-
end
|
38
|
-
it "should give the li the default id (stringified key) if no id is specified in the html_options" do
|
39
|
-
HTML::Selector.new('ul li#invoices').select(render).should have(1).entries
|
40
|
-
end
|
41
|
-
it "should not apply the the default id where there is an id specified in the html_options" do
|
42
|
-
HTML::Selector.new('ul li#users').select(render).should be_empty
|
43
|
-
end
|
44
32
|
|
33
|
+
context 'concerning html attributes' do
|
34
|
+
context 'default case (no options defined for link tag)' do
|
35
|
+
it "should pass the specified html_options to the li element" do
|
36
|
+
HTML::Selector.new('li[style=float:right]').select(render).should have(1).entries
|
37
|
+
end
|
38
|
+
it "should give the li the id specified in the html_options" do
|
39
|
+
HTML::Selector.new('li#my_id').select(render).should have(1).entries
|
40
|
+
end
|
41
|
+
it "should give the li the default id (stringified key) if no id is specified in the html_options" do
|
42
|
+
HTML::Selector.new('ul li#invoices').select(render).should have(1).entries
|
43
|
+
end
|
44
|
+
it "should not apply the the default id where there is an id specified in the html_options" do
|
45
|
+
HTML::Selector.new('ul li#users').select(render).should be_empty
|
46
|
+
end
|
47
|
+
end
|
48
|
+
context 'with attributes defined for the link tag as well' do
|
49
|
+
it "should add the link attributes to the link" do
|
50
|
+
HTML::Selector.new('a[style=float:left]').select(render).should have(1).entries
|
51
|
+
end
|
52
|
+
it "should add the li attributes to the li element" do
|
53
|
+
HTML::Selector.new('li[style=float:right]').select(render).should have(1).entries
|
54
|
+
end
|
55
|
+
it "should give the li the default id (stringified key) if no id is specified in the html_options for the li-element" do
|
56
|
+
HTML::Selector.new('ul li#invoices').select(render).should have(1).entries
|
57
|
+
end
|
58
|
+
it "should not apply the the default id where there is an id specified in the html_options for th li-element" do
|
59
|
+
HTML::Selector.new('ul li#users').select(render).should be_empty
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
45
64
|
context 'with current_navigation set' do
|
46
65
|
it "should mark the matching li-item as selected (with the css_class specified in configuration)" do
|
47
66
|
HTML::Selector.new('li.selected').select(render(:invoices)).should have(1).entries
|
@@ -49,7 +68,6 @@ describe SimpleNavigation::Renderer::List do
|
|
49
68
|
it "should also mark the links inside the selected li's as selected" do
|
50
69
|
HTML::Selector.new('li.selected a.selected').select(render(:invoices)).should have(1).entries
|
51
70
|
end
|
52
|
-
|
53
71
|
end
|
54
72
|
|
55
73
|
context 'without current_navigation set' do
|
@@ -125,5 +143,47 @@ describe SimpleNavigation::Renderer::List do
|
|
125
143
|
end
|
126
144
|
end
|
127
145
|
|
146
|
+
describe 'link_options_for' do
|
147
|
+
before(:each) do
|
148
|
+
setup_renderer_for SimpleNavigation::Renderer::List, :rails, options
|
149
|
+
end
|
150
|
+
context 'no link options specified' do
|
151
|
+
context 'method specified' do
|
152
|
+
context 'item selected' do
|
153
|
+
before(:each) do
|
154
|
+
@item = stub(:item, :method => :delete, :selected_class => 'selected', :html_options => {})
|
155
|
+
end
|
156
|
+
it {@renderer.send(:link_options_for, @item).should == {:method => :delete, :class => 'selected'}}
|
157
|
+
end
|
158
|
+
context 'item not selected' do
|
159
|
+
before(:each) do
|
160
|
+
@item = stub(:item, :method => :delete, :selected_class => nil, :html_options => {})
|
161
|
+
end
|
162
|
+
it {@renderer.send(:link_options_for, @item).should == {:method => :delete}}
|
163
|
+
end
|
164
|
+
end
|
165
|
+
context 'method not specified' do
|
166
|
+
context 'item selected' do
|
167
|
+
before(:each) do
|
168
|
+
@item = stub(:item, :method => nil, :selected_class => 'selected', :html_options => {})
|
169
|
+
end
|
170
|
+
it {@renderer.send(:link_options_for, @item).should == {:class => 'selected'}}
|
171
|
+
end
|
172
|
+
context 'item not selected' do
|
173
|
+
before(:each) do
|
174
|
+
@item = stub(:item, :method => nil, :selected_class => nil, :html_options => {})
|
175
|
+
end
|
176
|
+
it {@renderer.send(:link_options_for, @item).should == {}}
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
context 'link options specified' do
|
181
|
+
before(:each) do
|
182
|
+
@item = stub(:item, :method => :delete, :selected_class => 'selected', :html_options => {:link => {:class => 'link_class', :style => 'float:left'}})
|
183
|
+
end
|
184
|
+
it {@renderer.send(:link_options_for, @item).should == {:method => :delete, :class => 'link_class selected', :style => 'float:left'}}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
128
188
|
end
|
129
189
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -35,7 +35,7 @@ def primary_items
|
|
35
35
|
[
|
36
36
|
[:users, 'users', 'first_url', {:id => 'my_id'}],
|
37
37
|
[:invoices, 'invoices', 'second_url', {}],
|
38
|
-
[:accounts, 'accounts', 'third_url', {:style => 'float:right'}]
|
38
|
+
[:accounts, 'accounts', 'third_url', {:style => 'float:right', :link => {:style => 'float:left'}}]
|
39
39
|
]
|
40
40
|
end
|
41
41
|
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-navigation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 3
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
|
10
|
-
version: 3.0.0.beta2
|
9
|
+
version: 3.0.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Andi Schacke
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-09-
|
17
|
+
date: 2010-09-28 00:00:00 +02:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|