simple_navigation_bootstrap 1.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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +28 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +6 -0
- data/AUTHORS +2 -0
- data/Gemfile +14 -0
- data/LICENSE +19 -0
- data/README.md +166 -0
- data/Rakefile +6 -0
- data/lib/simple_navigation_bootstrap.rb +14 -0
- data/lib/simple_navigation_bootstrap/bootstrap2.rb +20 -0
- data/lib/simple_navigation_bootstrap/bootstrap3.rb +20 -0
- data/lib/simple_navigation_bootstrap/bootstrap_base.rb +81 -0
- data/lib/simple_navigation_bootstrap/engine.rb +4 -0
- data/lib/simple_navigation_bootstrap/errors.rb +8 -0
- data/lib/simple_navigation_bootstrap/rendered_item.rb +125 -0
- data/lib/simple_navigation_bootstrap/version.rb +15 -0
- data/simple_navigation_bootstrap.gemspec +29 -0
- data/spec/lib/simple_navigation_bootstrap/bootstrap2_spec.rb +53 -0
- data/spec/lib/simple_navigation_bootstrap/bootstrap3_spec.rb +209 -0
- data/spec/lib/simple_navigation_bootstrap/exceptions_spec.rb +7 -0
- data/spec/lib/simple_navigation_renderers_spec.rb +11 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/test_helper.rb +139 -0
- data/vendor/assets/stylesheets/bootstrap2_dropdown_submenu.css.scss +51 -0
- data/vendor/assets/stylesheets/bootstrap2_navbar_divider_vertical.css.scss +11 -0
- data/vendor/assets/stylesheets/simple_navigation_bootstrap.css.scss +3 -0
- data/vendor/assets/stylesheets/simple_navigation_bootstrap_overrides.css.scss +15 -0
- metadata +179 -0
data/.travis.yml
ADDED
data/AUTHORS
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in simple_navigation_bootstrap.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
# Get master branch of simple-navigation to fix 'undefined class ::Rails::Railtie' error
|
7
|
+
# See: https://github.com/codeplant/simple-navigation/commit/fb2c41511ade34e1ed6857a89ab2c7f1eead3ecb
|
8
|
+
gem 'simple-navigation', git: 'https://github.com/codeplant/simple-navigation.git'
|
9
|
+
|
10
|
+
# README edition
|
11
|
+
gem 'gh-preview'
|
12
|
+
|
13
|
+
# CodeClimate Test Coverage
|
14
|
+
gem 'codeclimate-test-reporter', group: :test, require: nil
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
## SimpleNavigation Bootstrap
|
2
|
+
|
3
|
+
[](https://github.com/jbox-web/simple_navigation_bootstrap/blob/master/LICENSE)
|
4
|
+
[](https://github.com/jbox-web/simple_navigation_bootstrap/releases/latest)
|
5
|
+
[](https://travis-ci.org/jbox-web/simple_navigation_bootstrap)
|
6
|
+
[](https://codeclimate.com/github/jbox-web/simple_navigation_bootstrap)
|
7
|
+
[](https://codeclimate.com/github/jbox-web/simple_navigation_bootstrap/coverage)
|
8
|
+
[](https://gemnasium.com/github.com/jbox-web/simple_navigation_bootstrap)
|
9
|
+
|
10
|
+
This gem adds Bootstrap renderers for Simple Navigation. For now, it is include renderers for:
|
11
|
+
|
12
|
+
* [Bootstrap 2 navigation](http://getbootstrap.com/2.3.2/components.html#navbar)
|
13
|
+
* [Bootstrap 3 navigation](http://getbootstrap.com/components/#navbar)
|
14
|
+
|
15
|
+
With these renderers you will be able create **any Bootstrap navigation elements**, such as: **submenu**, **navbar-text**, **divider**, **header**.
|
16
|
+
As well as add **icons** to menu elements, such as: Glyphicons, Font Awesome icons, even custom icons. Also you have **split** option for main menu containing submenu.
|
17
|
+
|
18
|
+
*This gem is fork of [ShPakvel/simple\_navigation\_renderers](https://github.com/ShPakvel/simple_navigation_renderers).*
|
19
|
+
*After a year of waiting for [PR merge](https://github.com/ShPakvel/simple_navigation_renderers/pull/14) without any news from the author, I decided to fork it.*
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
gem 'simple_navigation_bootstrap'
|
27
|
+
```
|
28
|
+
|
29
|
+
and then execute:
|
30
|
+
|
31
|
+
```console
|
32
|
+
$ bundle install
|
33
|
+
```
|
34
|
+
|
35
|
+
Or install it yourself as:
|
36
|
+
|
37
|
+
```console
|
38
|
+
$ gem install simple_navigation_bootstrap
|
39
|
+
```
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
### Simply set up renderer and you are done!!
|
44
|
+
|
45
|
+
There are two ways to say that you want to use any of renderers.
|
46
|
+
|
47
|
+
1. You can specify it in you view as a parameter to `render_navigation`:
|
48
|
+
|
49
|
+
```erb
|
50
|
+
...
|
51
|
+
<%= render_navigation(expand_all: true, renderer: :bootstrap2) %>
|
52
|
+
# Or
|
53
|
+
<%= render_navigation(expand_all: true, renderer: :bootstrap3) %>
|
54
|
+
...
|
55
|
+
```
|
56
|
+
|
57
|
+
2. Or you can set it in the very navigation configuration file (e.g. `config/navigation.rb`):
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
SimpleNavigation::Configuration.run do |navigation|
|
61
|
+
navigation.renderer = SimpleNavigationBootstrap::Bootstrap2
|
62
|
+
# or
|
63
|
+
navigation.renderer = SimpleNavigationBootstrap::Bootstrap3
|
64
|
+
# navigation itself goes here...
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
## Explicit example of using all features
|
69
|
+
|
70
|
+
I think you already using `simple-navigation` gem and know how to define navigation items.
|
71
|
+
If not, you can always look at the [configuration instructions](https://github.com/andi/simple-navigation/wiki/Configuration) on the Simple Navigation wiki or read comments and examples in the generated by default `config/navigation.rb` file.
|
72
|
+
|
73
|
+
In addition to standard options you can use ones specific for Bootstrap renderers.
|
74
|
+
Lets look at the example:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
SimpleNavigation::Configuration.run do |navigation|
|
78
|
+
navigation.renderer = SimpleNavigationRenderers::Bootstrap3
|
79
|
+
|
80
|
+
navigation.items do |primary|
|
81
|
+
primary.item :news, { icon: 'fa fa-fw fa-bullhorn', text: 'News' }, news_index_path
|
82
|
+
primary.item :concerts, 'Concerts', concerts_path
|
83
|
+
primary.item :video, 'Video', videos_path
|
84
|
+
primary.item :divider_before_info, '#', divider: true
|
85
|
+
primary.item :info, { icon: 'fa fa-fw fa-book', title: 'Info' }, info_index_path, split: true do |info_nav|
|
86
|
+
info_nav.item :main_info_page, 'Main info page', info_path(:main_info_page)
|
87
|
+
info_nav.item :about_info_page, 'About', info_path(:about_info_page)
|
88
|
+
info_nav.item :misc_info_pages, 'Misc.' do |misc_page|
|
89
|
+
misc_page.item :header_misc_pages, 'Misc. Pages', header: true
|
90
|
+
Info.all.each do |info_page|
|
91
|
+
misc_page.item :"#{info_page.permalink}", info_page.title, info_path(info_page)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
info_nav.item :divider_before_contact_info_page, '#', divider: true
|
95
|
+
info_nav.item :contact_info_page, 'Contact', info_path(:contact_info_page)
|
96
|
+
end
|
97
|
+
primary.item :signed_in, 'Signed in as Pavel Shpak', navbar_text: true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
## Features
|
103
|
+
|
104
|
+
Specific options used in the example:
|
105
|
+
|
106
|
+
Option | Description
|
107
|
+
---------------|--------------
|
108
|
+
`:split` | Use it to split first level item link with caret. If you add `split: true` option to item, then caret itself will toggle first level submenu and link will have standard behaviour, instead of toggle submenu. You can use `:split` only with first level items, for the rest it will not do anything.
|
109
|
+
`:navbar_text` | Use it as `navbar_text: true` to add Bootstrap `navbar-text`.
|
110
|
+
`:divider` | Use it to add Bootstrap menu divider. if you add `divider: true` option to first level item, then it will create li-tag with `divider-vertical` Bootstrap 2 class. (You can add `divider-vertical` class to Bootstrap 3 - see below). For the second level item and deeper it will create `li` tag with class `divider` (which exists in both, Bootstrap 2 and 3).
|
111
|
+
`:header` | Use it as `header: true` to add Bootstrap menu header. You can use `:header` only with submenus, for the first level items it will not do anything.
|
112
|
+
`:name hash` | Use it in place of `:name` if you want. Hash can have three keys: `:text`, `:icon` and `:title`, which is only recognized. You can use it together or separatly, but at least one of `:text` and `:icon` parameters should be provided.
|
113
|
+
|
114
|
+
Example for `:name hash`:
|
115
|
+
|
116
|
+
* `{ text: 'News', icon: 'fa fa-fw fa-bullhorn' }` will create Font Awesome icon and add text after it (name of the item)
|
117
|
+
* `{ icon: 'glyphicon glyphicon-book', title: 'Info' }` will create Bootstrap icon with title without any text after it
|
118
|
+
|
119
|
+
## Notes
|
120
|
+
|
121
|
+
1. Bootstrap 3 has only one level submenu. If you want to use nested submenus as in example above, import `bootstrap2_dropdown_submenu.css.scss` file into your Sass file (e.g. `application.css.scss`) as following:
|
122
|
+
|
123
|
+
```scss
|
124
|
+
@import "bootstrap2_dropdown_submenu";
|
125
|
+
```
|
126
|
+
|
127
|
+
2. Bootstrap 3 has not `divider-vertical` class. If you want to use it as in example above, import `bootstrap2_navbar_divider_vertical.css.scss` file:
|
128
|
+
|
129
|
+
```scss
|
130
|
+
@import "bootstrap2_navbar_divider_vertical";
|
131
|
+
```
|
132
|
+
|
133
|
+
3. You may also want to include following file which changes some first level submenu style:
|
134
|
+
|
135
|
+
```scss
|
136
|
+
@import "simple_navigation_bootstrap_overrides";
|
137
|
+
```
|
138
|
+
|
139
|
+
4. or you can add them all together:
|
140
|
+
|
141
|
+
```scss
|
142
|
+
@import "simple_navigation_bootstrap";
|
143
|
+
```
|
144
|
+
|
145
|
+
## Test
|
146
|
+
|
147
|
+
Just run following commands:
|
148
|
+
|
149
|
+
```console
|
150
|
+
$ bundle install
|
151
|
+
$ rake
|
152
|
+
```
|
153
|
+
|
154
|
+
|
155
|
+
## Contributing
|
156
|
+
|
157
|
+
1. Fork it
|
158
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
159
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
160
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
161
|
+
5. Create new Pull Request
|
162
|
+
|
163
|
+
|
164
|
+
## Contributors
|
165
|
+
|
166
|
+
A big thank to [them](https://github.com/jbox-web/simple_navigation_bootstrap/blob/master/AUTHORS) for their contribution!
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'simple-navigation'
|
3
|
+
require 'simple_navigation_bootstrap/errors'
|
4
|
+
require 'simple_navigation_bootstrap/rendered_item'
|
5
|
+
require 'simple_navigation_bootstrap/bootstrap_base'
|
6
|
+
require 'simple_navigation_bootstrap/bootstrap2'
|
7
|
+
require 'simple_navigation_bootstrap/bootstrap3'
|
8
|
+
require 'simple_navigation_bootstrap/engine' if defined? Rails::Engine
|
9
|
+
|
10
|
+
module SimpleNavigationBootstrap
|
11
|
+
end
|
12
|
+
|
13
|
+
SimpleNavigation.register_renderer(bootstrap2: SimpleNavigationBootstrap::Bootstrap2)
|
14
|
+
SimpleNavigation.register_renderer(bootstrap3: SimpleNavigationBootstrap::Bootstrap3)
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module SimpleNavigationBootstrap
|
2
|
+
module BootstrapBase
|
3
|
+
|
4
|
+
def render(item_container)
|
5
|
+
if skip_if_empty? && item_container.empty?
|
6
|
+
''
|
7
|
+
else
|
8
|
+
# Generate list of items
|
9
|
+
list_content = with_bootstrap_configs do
|
10
|
+
item_container.items.inject([]) do |list, item|
|
11
|
+
list << render_item(self, item, item_container.level, bootstrap_version)
|
12
|
+
end.join
|
13
|
+
end
|
14
|
+
|
15
|
+
# Set CSS class for container :
|
16
|
+
# class = 'nav' if level == 1
|
17
|
+
# class = 'dropdown-menu' if level > 1
|
18
|
+
item_container.dom_class = [item_container.dom_class, container_class(item_container.level)].flatten.compact.join(' ')
|
19
|
+
|
20
|
+
# Generate the final list
|
21
|
+
content_tag(:ul, list_content, id: item_container.dom_id, class: item_container.dom_class)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
|
29
|
+
def render_item(*args)
|
30
|
+
SimpleNavigationBootstrap::RenderedItem.new(*args).to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def container_class(level)
|
35
|
+
remove_navigation_class = options.delete(:remove_navigation_class){ false }
|
36
|
+
if level == 1
|
37
|
+
remove_navigation_class ? '' : ['nav', navigation_class].compact
|
38
|
+
else
|
39
|
+
'dropdown-menu'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def with_bootstrap_configs
|
45
|
+
# Get current config
|
46
|
+
sn_config = SimpleNavigation.config
|
47
|
+
|
48
|
+
# Save current config
|
49
|
+
config_selected_class = sn_config.selected_class
|
50
|
+
config_name_generator = sn_config.name_generator
|
51
|
+
sn_config.selected_class = 'active'
|
52
|
+
|
53
|
+
# name_generator should be proc (not lambda or method) to be compatible with earlier versions of simple-navigation
|
54
|
+
sn_config.name_generator = proc do |name, item|
|
55
|
+
config_name_generator.call(prepare_name(name), item)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generate menu
|
59
|
+
result = yield
|
60
|
+
|
61
|
+
# Restore config
|
62
|
+
sn_config.name_generator = config_name_generator
|
63
|
+
sn_config.selected_class = config_selected_class
|
64
|
+
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def prepare_name(name)
|
70
|
+
return name unless name.is_a?(Hash)
|
71
|
+
|
72
|
+
if name[:icon]
|
73
|
+
icon_options = { class: name[:icon], title: name[:title] }.reject { |_, v| v.nil? }
|
74
|
+
content_tag(:span, '', icon_options) + ' ' + (name[:text] || '')
|
75
|
+
else
|
76
|
+
name[:text] || (raise SimpleNavigationBootstrap::InvalidHash)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module SimpleNavigationBootstrap
|
2
|
+
# Exception raised when you set Hash without both 'text' and 'icon' parameters as Item 'name' parameter
|
3
|
+
class InvalidHash < StandardError
|
4
|
+
def initialize(msg = "Hash does not contain any of parameters: 'text', 'icon'")
|
5
|
+
super
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module SimpleNavigationBootstrap
|
2
|
+
class RenderedItem
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
attr_reader :renderer
|
6
|
+
def_delegators :renderer, :link_to, :content_tag, :include_sub_navigation?, :render_sub_navigation_for
|
7
|
+
|
8
|
+
def initialize(renderer, item, level, bootstrap_version)
|
9
|
+
@renderer = renderer
|
10
|
+
@item = item
|
11
|
+
@level = level
|
12
|
+
@bootstrap_version = bootstrap_version
|
13
|
+
|
14
|
+
@options = item.html_options
|
15
|
+
@navbar_text = options.delete(:navbar_text)
|
16
|
+
@divider = options.delete(:divider) { false }
|
17
|
+
@header = options.delete(:header) { false }
|
18
|
+
@split = options.delete(:split) { false }
|
19
|
+
@skip_caret = options.delete(:skip_caret) { false }
|
20
|
+
@link_options = @item.link_html_options || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
if navbar_text
|
26
|
+
li_text
|
27
|
+
elsif divider
|
28
|
+
li_divider
|
29
|
+
elsif header && (level != 1)
|
30
|
+
li_header
|
31
|
+
else
|
32
|
+
li_link
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
|
40
|
+
attr_reader :item, :level, :bootstrap_version, :options, :navbar_text, :divider, :header, :split, :skip_caret, :link_options
|
41
|
+
|
42
|
+
def li_text
|
43
|
+
content_tag(:li, content_tag(:p, item.name, class: 'navbar-text'), options)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def li_divider
|
48
|
+
css_class = level == 1 ? 'divider-vertical' : 'divider'
|
49
|
+
options[:class] = [options[:class], css_class].flatten.compact.join(' ')
|
50
|
+
content_tag(:li, '', options)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def li_header
|
55
|
+
css_class = bootstrap_version == 3 ? 'dropdown-header' : 'nav-header'
|
56
|
+
options[:class] = [options[:class], css_class].flatten.compact.join(' ')
|
57
|
+
content_tag(:li, item.name, options)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def li_link
|
62
|
+
if include_sub_navigation?(item)
|
63
|
+
if level == 1
|
64
|
+
if split
|
65
|
+
splitted_simple_part + splitted_dropdown_part
|
66
|
+
else
|
67
|
+
content = [item.name]
|
68
|
+
content << caret unless skip_caret
|
69
|
+
content = content.join(' ').html_safe
|
70
|
+
dropdown_part(content)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
content_tag(:li, dropdown_submenu_link, options)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
content_tag(:li, simple_link, options)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def splitted_simple_part
|
82
|
+
main_li_options = options.dup
|
83
|
+
main_li_options[:class] = [main_li_options[:class], 'dropdown-split-left'].flatten.compact.join(' ')
|
84
|
+
content_tag(:li, simple_link, main_li_options)
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def splitted_dropdown_part
|
89
|
+
item.sub_navigation.dom_class = [item.sub_navigation.dom_class, 'pull-right'].flatten.compact.join(' ')
|
90
|
+
link_options = {}
|
91
|
+
options[:id] = nil
|
92
|
+
options[:class] = [options[:class], 'dropdown-split-right'].flatten.compact.join(' ')
|
93
|
+
dropdown_part(caret)
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def dropdown_part(name)
|
98
|
+
options[:class] = [options[:class], 'dropdown'].flatten.compact.join(' ')
|
99
|
+
link_options[:class] = [link_options[:class], 'dropdown-toggle'].flatten.compact.join(' ')
|
100
|
+
link_options[:"data-toggle"] = 'dropdown'
|
101
|
+
link_options[:"data-target"] = '#'
|
102
|
+
|
103
|
+
content = link_to(name, '#', link_options) + render_sub_navigation_for(item)
|
104
|
+
content_tag(:li, content, options)
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def caret
|
109
|
+
content_tag(:b, '', class: 'caret')
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def dropdown_submenu_link
|
114
|
+
options[:class] = [options[:class], 'dropdown-submenu'].flatten.compact.join(' ')
|
115
|
+
simple_link + render_sub_navigation_for(item)
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
def simple_link
|
120
|
+
link_options[:method] ||= item.method
|
121
|
+
link_to(item.name, (item.url || '#'), link_options)
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|