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.
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ cache: bundler
3
+ sudo: false
4
+ rvm:
5
+ - 2.3.1
6
+ - 2.2.5
data/AUTHORS ADDED
@@ -0,0 +1,2 @@
1
+ Nicolas Rodriguez <nrodriguez@jbox-web.com>
2
+ Pavel Shpak <shpakvel@gmail.com>
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
+ [![GitHub license](https://img.shields.io/github/license/jbox-web/simple_navigation_bootstrap.svg)](https://github.com/jbox-web/simple_navigation_bootstrap/blob/master/LICENSE)
4
+ [![GitHub release](https://img.shields.io/github/release/jbox-web/simple_navigation_bootstrap.svg)](https://github.com/jbox-web/simple_navigation_bootstrap/releases/latest)
5
+ [![Build Status](https://travis-ci.org/jbox-web/simple_navigation_bootstrap.svg?branch=master)](https://travis-ci.org/jbox-web/simple_navigation_bootstrap)
6
+ [![Code Climate](https://codeclimate.com/github/jbox-web/simple_navigation_bootstrap/badges/gpa.svg)](https://codeclimate.com/github/jbox-web/simple_navigation_bootstrap)
7
+ [![Test Coverage](https://codeclimate.com/github/jbox-web/simple_navigation_bootstrap/badges/coverage.svg)](https://codeclimate.com/github/jbox-web/simple_navigation_bootstrap/coverage)
8
+ [![Dependency Status](https://gemnasium.com/badges/github.com/jbox-web/simple_navigation_bootstrap.svg)](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,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -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,20 @@
1
+ module SimpleNavigationBootstrap
2
+ class Bootstrap2 < SimpleNavigation::Renderer::Base
3
+
4
+ include BootstrapBase
5
+
6
+
7
+ private
8
+
9
+
10
+ def bootstrap_version
11
+ 2
12
+ end
13
+
14
+
15
+ def navigation_class
16
+ nil
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module SimpleNavigationBootstrap
2
+ class Bootstrap3 < SimpleNavigation::Renderer::Base
3
+
4
+ include BootstrapBase
5
+
6
+
7
+ private
8
+
9
+
10
+ def bootstrap_version
11
+ 3
12
+ end
13
+
14
+
15
+ def navigation_class
16
+ 'navbar-nav'
17
+ end
18
+
19
+ end
20
+ end
@@ -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,4 @@
1
+ module SimpleNavigationBootstrap
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ 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