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 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). Either specify
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
- renderer_class = if options[:renderer]
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
- renderer_class.render(self)
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
- html_options = item.html_options
16
- li_content = link_to(item.name, item.url, :class => item.selected_class, :method => item.method)
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, html_options)
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: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 3
7
7
  - 0
8
8
  - 0
9
- - beta2
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-02 00:00:00 +02:00
17
+ date: 2010-09-28 00:00:00 +02:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency