selected_links 0.0.1 → 0.0.2
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +4 -0
- data/README.md +11 -1
- data/lib/selected_links/action_view.rb +35 -35
- data/lib/selected_links/link.rb +60 -53
- data/lib/selected_links/railtie.rb +7 -7
- data/lib/selected_links/version.rb +1 -1
- data/lib/selected_links.rb +10 -7
- data/spec/selected_links/link_spec.rb +160 -147
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62a30a37be7b8ed9394a6c728b664f415a7132ee
|
4
|
+
data.tar.gz: a0b6aa5bb7c513ebb8b81a1cd89788425ee72034
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 390d347634eeacedf9a152afb93f73def7045399ee5f87932acd291ae27a4fb5caf480216e2e8c55df0ec31c82b48d467eb80aeecd743e6209d7c1f4b84b73c8
|
7
|
+
data.tar.gz: 9c24559d76be4f71a83814976d0c50fa78c278f0514418f81a7d51fb783e27d95c8c40c4ca0adcec578fa9fa19b8db2f51ba93e944cc25e91d4efc8ffd341cb9
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# Selected Links
|
2
|
+
|
3
|
+
[](https://travis-ci.org/kainage/selected_links)
|
2
4
|
|
3
5
|
Adds a link helper to ActionView::Base to that adds a class of _selected_
|
4
6
|
to the link when matched to a pattern, usually a url.
|
@@ -29,6 +31,14 @@ SelectedLinks.setup do |config|
|
|
29
31
|
end
|
30
32
|
```
|
31
33
|
|
34
|
+
You can also change the fallback behaviour to check the name if the matcher fails
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
SelectedLinks.setup do |config|
|
38
|
+
config.fallback_to_name = false
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
32
42
|
### Useage
|
33
43
|
|
34
44
|
To make this link have a class of _selected_ when the url is at the top level:
|
@@ -1,41 +1,41 @@
|
|
1
1
|
require 'action_view'
|
2
2
|
|
3
3
|
module SelectedLinks
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
4
|
+
# Usage is the same as link_to and takes an optional regex argument matcher.
|
5
|
+
#
|
6
|
+
# <%= selectable_link_to 'Home', root_url, :matcher => '\/\z' %>
|
7
|
+
#
|
8
|
+
# That would make this link have a class of 'selected' when the url is at the top level.
|
9
|
+
#
|
10
|
+
# <%= selectable_link_to 'Topics', topics_url, :matcher => 'topic' %>
|
11
|
+
#
|
12
|
+
# This will make the nav link selected when the url has 'topic' in it anywhere.
|
13
|
+
#
|
14
|
+
# <% selectable_link_to community_url, :matcher => 'topic' do %>
|
15
|
+
# <%= content_tag :span, 'Community', :class => 'foo' %>
|
16
|
+
# <% end %>
|
17
|
+
#
|
18
|
+
# Blocks still work and this will do the same thing as the previous example.
|
19
|
+
#
|
20
|
+
# <%= selectable_link_to 'ABOUT', about_url %>
|
21
|
+
#
|
22
|
+
# Without a matcher option and NOT in the block form, this will look for 'about' in the url.
|
23
|
+
module ActionView
|
24
|
+
def selectable_link_to(*args, &block)
|
25
|
+
link = Link.new(*args, &block).generate
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
# Add default source if none was given.
|
28
|
+
unless link.source
|
29
|
+
link.source = instance_eval(SelectedLinks.default_source)
|
30
|
+
# Can run generate again because there will for sure be no match here yet.
|
31
|
+
link.generate
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
if block_given?
|
35
|
+
raw link_to link.options, link.html_options, &block
|
36
|
+
else
|
37
|
+
raw link_to link.name, link.options, link.html_options
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
41
|
end
|
data/lib/selected_links/link.rb
CHANGED
@@ -1,55 +1,62 @@
|
|
1
1
|
module SelectedLinks
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
2
|
+
class Link
|
3
|
+
attr_reader :name, :options, :html_options
|
4
|
+
attr_accessor :source
|
5
|
+
|
6
|
+
def initialize(*args, &block)
|
7
|
+
@name, @options, @html_options = parse_args(block_given?, *args)
|
8
|
+
@matcher = @html_options[:matcher]
|
9
|
+
@source = @html_options[:source]
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate
|
13
|
+
merge_classes if is_match?
|
14
|
+
cleanup
|
15
|
+
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def parse_args(block, *args)
|
22
|
+
if block
|
23
|
+
[nil, args.first, args.second || {}]
|
24
|
+
else
|
25
|
+
[args[0], args[1], args[2] || {}]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def merge_classes
|
30
|
+
@html_options.merge!({class: 'selected'}) { |key, old_v, new_v| [old_v, new_v].join(' ') }
|
31
|
+
end
|
32
|
+
|
33
|
+
def is_match?
|
34
|
+
# Always return true if the source and the matcher match.
|
35
|
+
return true if url_match?(@source, @matcher)
|
36
|
+
# If not check for fallback and presence of @matcher and check again if necessary.
|
37
|
+
if (@matcher && SelectedLinks.fallback_to_name) || !@matcher
|
38
|
+
return url_match?(@source, @name)
|
39
|
+
else
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def url_match?(source, matcher)
|
45
|
+
return false unless matcher # nil.to_s returns ""
|
46
|
+
source =~ /#{matcher}/i
|
47
|
+
end
|
48
|
+
|
49
|
+
def cleanup
|
50
|
+
remove_matcher
|
51
|
+
remove_source
|
52
|
+
end
|
53
|
+
|
54
|
+
def remove_matcher
|
55
|
+
@html_options.delete(:matcher)
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_source
|
59
|
+
@html_options.delete(:source)
|
60
|
+
end
|
61
|
+
end
|
55
62
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module SelectedLinks
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer 'selected_links.action_view_extension' do
|
4
|
+
ActiveSupport.on_load :action_view do
|
5
|
+
include ActionView
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
9
|
end
|
data/lib/selected_links.rb
CHANGED
@@ -3,16 +3,19 @@ require 'selected_links/link'
|
|
3
3
|
require 'selected_links/action_view'
|
4
4
|
|
5
5
|
if defined? Rails
|
6
|
-
|
6
|
+
require 'selected_links/railtie'
|
7
7
|
else
|
8
|
-
|
8
|
+
ActionView::Base.send(:include, SelectedLinks::ActionView)
|
9
9
|
end
|
10
10
|
|
11
11
|
module SelectedLinks
|
12
|
-
|
13
|
-
|
12
|
+
mattr_accessor :default_source
|
13
|
+
@@default_source = 'request.path'
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
mattr_accessor :fallback_to_name
|
16
|
+
@@fallback_to_name = false
|
17
|
+
|
18
|
+
def self.setup
|
19
|
+
yield self
|
20
|
+
end
|
18
21
|
end
|
@@ -1,151 +1,164 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SelectedLinks::Link do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
4
|
+
describe "constructing a link" do
|
5
|
+
context "without a block" do
|
6
|
+
context "with valid options" do
|
7
|
+
before :each do
|
8
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'foo')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a name" do
|
12
|
+
@link.name.should eq 'Name'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have options" do
|
16
|
+
@link.options.should eq 'options'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have have html_options of a hash with two items" do
|
20
|
+
@link.html_options.should be_a(Hash)
|
21
|
+
@link.html_options.size.should eq 2
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with a block" do
|
26
|
+
context "with valid options" do
|
27
|
+
before :each do
|
28
|
+
@link = SelectedLinks::Link.new 'options', :source => '/foo', :matcher => 'foo' do
|
29
|
+
'Block Content'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should not have a name" do
|
34
|
+
@link.name.should be_nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have options" do
|
38
|
+
@link.options.should eq 'options'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have have html_options of a hash with two items" do
|
42
|
+
@link.html_options.should be_a(Hash)
|
43
|
+
@link.html_options.size.should eq 2
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "with valid options" do
|
51
|
+
before :each do
|
52
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'foo')
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should remove source option" do
|
56
|
+
@link.send(:remove_source)
|
57
|
+
@link.html_options.has_key?(:source).should be_false
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should remove matcher option" do
|
61
|
+
@link.send(:remove_matcher)
|
62
|
+
@link.html_options.has_key?(:matcher).should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should remove both source and matcher options" do
|
66
|
+
@link.send(:cleanup)
|
67
|
+
@link.html_options.has_key?(:source).should be_false
|
68
|
+
@link.html_options.has_key?(:matcher).should be_false
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "url_match?" do
|
72
|
+
it "should return true when url matches given strig" do
|
73
|
+
@link.send(:url_match?, '/hello', 'hello').should be_true
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return true when url partially matches string" do
|
77
|
+
@link.send(:url_match?, '/hello', 'ell').should be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return false when string does not match" do
|
81
|
+
@link.send(:url_match?, '/hello', 'world').should be_false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "for a matcher match" do
|
86
|
+
it "should return true for a match" do
|
87
|
+
@link.send(:is_match?).should be_true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return false for a non match" do
|
91
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/bar', :matcher => 'foo')
|
92
|
+
@link.send(:is_match?).should be_false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "for a named match" do
|
97
|
+
it "should return true for a named match" do
|
98
|
+
@link = SelectedLinks::Link.new('Foo', 'options', :source => '/foo')
|
99
|
+
@link.send(:is_match?).should be_true
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should return false for a non match" do
|
103
|
+
@link = SelectedLinks::Link.new('Bar', 'options', :source => '/foo')
|
104
|
+
@link.send(:is_match?).should be_false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "fallback to named path" do
|
109
|
+
it "should not fallback by default" do
|
110
|
+
@link = SelectedLinks::Link.new('Foo', 'options', :source => '/foo', :matcher => 'bar')
|
111
|
+
@link.send(:is_match?).should be_false
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should fallback when setting is on" do
|
115
|
+
SelectedLinks.fallback_to_name = true
|
116
|
+
@link = SelectedLinks::Link.new('Foo', 'options', :source => '/foo', :matcher => 'bar')
|
117
|
+
@link.send(:is_match?).should be_true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "fully constructed link" do
|
123
|
+
context "with a matcher link" do
|
124
|
+
it "should have a class of selected added" do
|
125
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'foo').generate
|
126
|
+
@link.html_options[:class].should =~ /selected/
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should not have a class of selected if there was not a match" do
|
130
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'bar').generate
|
131
|
+
@link.html_options[:class].should_not =~ /selected/
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "with a named link" do
|
136
|
+
it "should have a class of selected added" do
|
137
|
+
@link = SelectedLinks::Link.new('Foo', 'options', :source => '/foo').generate
|
138
|
+
@link.html_options[:class].should =~ /selected/
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should not have a class of selected if there was not a match" do
|
142
|
+
@link = SelectedLinks::Link.new('Bar', 'options', :source => '/foo').generate
|
143
|
+
@link.html_options[:class].should_not =~ /selected/
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "with an existing class" do
|
148
|
+
it "should have a class of selected added" do
|
149
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'foo', :class => 'nav').generate
|
150
|
+
@link.html_options[:class].should =~ /selected/
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should not have a class of selected if there was not a match" do
|
154
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'bar', :class => 'nav').generate
|
155
|
+
@link.html_options[:class].should_not =~ /selected/
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should have a space between the existing classes and the selected class' do
|
159
|
+
@link = SelectedLinks::Link.new('Name', 'options', :source => '/foo', :matcher => 'foo', :class => 'nav').generate
|
160
|
+
@link.html_options[:class].should == 'nav selected'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
151
164
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selected_links
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kainage
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,6 +75,7 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- .gitignore
|
77
77
|
- .rspec
|
78
|
+
- .travis.yml
|
78
79
|
- CHANGELOG.md
|
79
80
|
- Gemfile
|
80
81
|
- LICENSE.txt
|