simple-navigation 3.0.0.beta2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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