navigation_builder 1.0.0.beta1 → 1.0.0.beta2

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/README.md CHANGED
@@ -1,7 +1,115 @@
1
1
  Navigation Builder
2
2
  ==================
3
3
 
4
+ While at [RailsConf](http://www.railsconf.com) in the Spring/Summer of 2011, [Bruce Williams](http://github.com/bruce) mentioned a gem he wrote called ["Goose"](http://github.com/bruce/goose) that made generating navigation really easy. After looking through the code, I immediately thought of some tweaks that I wanted to make.
4
5
 
6
+ Rather than dealing with forks and pull requests, I just decided to spin off my own implementation from scratch, modeling the API after ActionView's FormBuilder.
7
+
8
+ #### That's great, let me see some code. ####
9
+
10
+ <% navigation_for :main do |nav| %>
11
+ <%= nav.link_to 'Home', '#' %>
12
+ <% end %>
13
+
14
+ Generates:
15
+
16
+ <ul>
17
+ <li>
18
+ <a href="#">Home</a>
19
+ </li>
20
+ </ul>
21
+
22
+ #### How do you mark a link as selected? ####
23
+
24
+ <% navigation_select 'Home' %>
25
+
26
+ Make sure that is called *before* the navigation is rendered in the view.
27
+
28
+ That will generate:
29
+
30
+ <ul>
31
+ <li class="selected">
32
+ <a href="#">Home</a>
33
+ </li>
34
+ </ul>
35
+
36
+ #### I don't want to use the class "selected". I'd rather use "current-page" ####
37
+
38
+ <% navigation_for :main, :selected_class => "current-page" do |nav| %>
39
+ <%= nav.link_to 'Home', '#' %>
40
+ <% end %>
41
+
42
+ #### But my links need additional HTML! ####
43
+
44
+ NavigationBuilder supports the same options that the `link_to` helper does:
45
+
46
+ <% navigation_for :sub_nav do |nav| %>
47
+ <% nav.link_to '#' do %>
48
+ <em>Home</em>
49
+ <span>Go to your home! Are you too good for your home?!</span>
50
+ <% end %>
51
+ <% end %>
52
+
53
+ #### Doesn't that mean that I need to repeat the entire `link_to` block when marking a link as selected? ####
54
+
55
+ Not at all, just use a regular expression:
56
+
57
+ <% navigation_select /Home/ %>
58
+
59
+ #### But what if I have multiple blocks of navigation on the page? ####
60
+
61
+ <% navigation_select 'Home', :in => :sub_nav %>
62
+
63
+ And in your layout:
64
+
65
+ <% navigation_for :sub_nav do |nav| %>
66
+ <%= nav.link_to 'Home', '#' %>
67
+ <% end %>
68
+
69
+ #### Well... what if I need an Ordered List! ####
70
+
71
+ <% navigation_for :main, :wrapper_tag => :ol do |nav| %>
72
+ <%= nav.link_to 'Home', '#' %>
73
+ <% end %>
74
+
75
+ Generates:
76
+
77
+ <ol>
78
+ <li class="selected">
79
+ <a href="#">Home</a>
80
+ </li>
81
+ </ol>
82
+
83
+ #### Nevermind, I hate lists. I just want DIVs. ####
84
+
85
+ <% navigation_for :main, :nav_item_tag => :div do |nav| %>
86
+ <%= nav.link_to 'Home', '#' %>
87
+ <% end %>
88
+
89
+ Generates:
90
+
91
+ <div class="selected">
92
+ <a href="#">Home</a>
93
+ </div>
94
+
95
+ #### My designer just said that's DIV-soup. ####
96
+
97
+ <% navigation_for :main, :nav_item_tag => false do |nav| %>
98
+ <%= nav.link_to 'Home', '#' %>
99
+ <% end %>
100
+
101
+ Generates:
102
+
103
+ <a href="#" class="selected">Home</a>
104
+
105
+ #### Why didn't you name this Gem "Wolfman" ####
106
+
107
+ Originally I was going to. But if you came across a method named "wolfman" in your view code, it would not be entirely clear as to what it was going to do.
108
+ So I just went with something boring and generic.
109
+
110
+ #### Well, you've thought of everything, haven't you! ####
111
+
112
+ Probably not, let me know if you have any feature requests!
5
113
 
6
114
  TODOs
7
115
  =====
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.beta1
1
+ 1.0.0.beta2
@@ -3,15 +3,19 @@ module ActionView
3
3
 
4
4
  module NavigationBuilderHelper
5
5
 
6
+ # Holds references to the currently selected links for each navigation block on the page.
6
7
  def navigation_builder
7
8
  @navigation_builder ||= { :main => nil }
8
9
  end
9
10
 
10
- # <% navigation_for :popup do |n| %>
11
- # <%= nav_to 'Design', :action => :design %>
12
- # <% end %>
13
- #
14
- # <%= navigation_select 'Design', :in => :popup %>
11
+ # Generates a block of navigation to be rendered to the page.
12
+ #
13
+ # Example:
14
+ # <% navigation_for :popup do |n| %>
15
+ # <%= nav_to 'Members', members_path %>
16
+ # <% end %>
17
+ #
18
+ # Generally speaking, this should go in your layout.
15
19
  def navigation_for( nav_name, options = {}, &block )
16
20
  raise ArgumentError, "Missing block" unless block_given?
17
21
 
@@ -27,11 +31,24 @@ module ActionView
27
31
  concat( tag(options[:wrapper_tag], options[:html], true) ) if navigation_has_wrapper?( options )
28
32
  yield builder.new(self, nav_name, options, block)
29
33
  concat("</#{options[:wrapper_tag]}>".html_safe) if navigation_has_wrapper?( options )
34
+
35
+ # Mark the navigation block has having been rendered
36
+ navigation_builder[nav_name] = true
30
37
  end
31
38
 
39
+ # Make sure this is called *before* your navigation is rendered.
40
+ # Ideally, this should go in your views and navigation_for() should
41
+ # be in your layout.
42
+ #
43
+ # Example:
44
+ # <%= navigation_select 'Members', :in => :popup %>
32
45
  def navigation_select( link_name, options = {} )
33
- options.reverse_merge!( :in => :main )
34
- navigation_builder[options[:in]] = link_name
46
+ if navigation_builder[options[:in]] == true
47
+ raise RuntimeError, "The #{options[:in]} navigation block has already been rendered. You cannot call navigation_select if navigation_for has already been called."
48
+ else
49
+ options.reverse_merge!( :in => :main )
50
+ navigation_builder[options[:in]] = link_name
51
+ end
35
52
  end
36
53
 
37
54
  private
@@ -44,21 +61,28 @@ module ActionView
44
61
 
45
62
  class NavigationBuilder
46
63
 
64
+ # Initializes the NavigationBuilder.
65
+ # You'll mostly likely never call this method directly.
47
66
  def initialize( template, nav_name, options, proc )
48
67
  @template, @nav_name, @options, @proc = template, nav_name, options, proc
49
68
  end
50
69
 
70
+ # Builds a link_to tag within the context of the current navigation block.
71
+ # This accepts all of the same parameters that ActiveView's link_to method
72
+ #
73
+ # Example:
74
+ # <%= nav.link_to 'Home', '#' %>
51
75
  def link_to( *args, &link_block )
52
76
  if block_given?
53
77
  name = @template.capture(&link_block)
54
78
  options = args.first || {}
55
- html_options = args.second
79
+ html_options = args.second || {}
56
80
 
57
81
  link_to_in_block( name, options, html_options, &link_block )
58
82
  else
59
83
  name = args[0]
60
84
  options = args[1] || {}
61
- html_options = args[2]
85
+ html_options = args[2] || {}
62
86
 
63
87
  link_to_in_html( name, options, html_options )
64
88
  end
@@ -69,7 +93,7 @@ module ActionView
69
93
  def link_to_in_block( name, options, html_options, &link_block )
70
94
  item_html_options = extract_item_options!( html_options )
71
95
 
72
- set_selected_link( name, item_html_options ) if is_selected?( name )
96
+ set_selected_link( name, html_options, item_html_options ) if is_selected?( name )
73
97
 
74
98
  @template.concat( @template.tag( @options[:nav_item_tag], item_html_options, true) ) if @options[:nav_item_tag]
75
99
  @template.link_to(options, html_options, &link_block)
@@ -79,7 +103,7 @@ module ActionView
79
103
  def link_to_in_html( name, options, html_options )
80
104
  item_html_options = extract_item_options!( html_options )
81
105
 
82
- set_selected_link( name, item_html_options ) if is_selected?( name )
106
+ set_selected_link( name, html_options, item_html_options ) if is_selected?( name )
83
107
 
84
108
  link_html = @template.link_to(name, options, html_options)
85
109
 
@@ -94,8 +118,16 @@ module ActionView
94
118
  options.try(:delete, :item_html) || {}
95
119
  end
96
120
 
97
- def set_selected_link( name, item_html_options )
98
- ((item_html_options[:class] ||= '') << " #{@options[:selected_class]}").strip!
121
+ def set_selected_link( name, html_options, item_html_options )
122
+ (selected_tag_options( html_options, item_html_options ) << " #{@options[:selected_class]}").strip!
123
+ end
124
+
125
+ def selected_tag_options( html_options, item_html_options )
126
+ if @options[:nav_item_tag]
127
+ item_html_options[:class] ||= ''
128
+ else
129
+ html_options[:class] ||= ''
130
+ end
99
131
  end
100
132
 
101
133
  def is_selected?( name )
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{navigation_builder}
8
- s.version = "1.0.0.beta1"
8
+ s.version = "1.0.0.beta2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Derek Lindahl"]
@@ -187,8 +187,19 @@ class TestNavigationBuilder < ActionView::TestCase
187
187
  assert_dom_equal expected, output_buffer
188
188
  end
189
189
 
190
+ should "generate HTML that highlights the currently selected navigation link even where there is no item tag" do
191
+ navigation_select 'Foo', :in => :main
192
+
193
+ navigation_for :main, :nav_item_tag => false do |nav|
194
+ concat nav.link_to( 'Foo', '#' )
195
+ end
190
196
 
191
- # TODO: Add test for "selected" class when there is no item tag
197
+ expected = [
198
+ "<a href=\"#\" class=\"selected\">Foo</a>"
199
+ ].join('')
200
+
201
+ assert_dom_equal expected, output_buffer
202
+ end
192
203
 
193
204
  should "generate HTML that highlights the currently selected navigation link by using a Regular Expression" do
194
205
  navigation_select /Foo/, :in => :main
@@ -211,4 +222,13 @@ class TestNavigationBuilder < ActionView::TestCase
211
222
  assert_dom_equal expected, output_buffer
212
223
  end
213
224
 
225
+ should "raise an exception if a link is selected AFTER the navigation has been rendered" do
226
+ assert_raises RuntimeError do
227
+ navigation_for :main do |nav|
228
+ concat nav.link_to( 'Foo', '#' )
229
+ end
230
+ navigation_select 'Foo', :in => :main
231
+ end
232
+ end
233
+
214
234
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: navigation_builder
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196353
4
+ hash: 62196359
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
10
  - beta
11
- - 1
12
- version: 1.0.0.beta1
11
+ - 2
12
+ version: 1.0.0.beta2
13
13
  platform: ruby
14
14
  authors:
15
15
  - Derek Lindahl