├── .gitignore
├── .jshintignore
├── Code
├── LICENSE
├── README.md
├── dist
├── ng-bootstrap-submenu.css
├── ng-bootstrap-submenu.css.map
├── ng-bootstrap-submenu.js
├── ng-bootstrap-submenu.min.css
├── ng-bootstrap-submenu.min.css.map
└── ng-bootstrap-submenu.min.js
├── example.html
├── gulpfile.js
├── lib
└── bootstrap-submenu-2.0.1-dist
│ ├── css
│ ├── bootstrap-submenu.css
│ ├── bootstrap-submenu.css.map
│ ├── bootstrap-submenu.min.css
│ └── bootstrap-submenu.min.css.map
│ └── js
│ ├── bootstrap-submenu.js
│ └── bootstrap-submenu.min.js
├── package.json
└── src
├── bootstrapSubmenu.html
├── bootstrapSubmenu.js
├── bootstrapSubmenuController.js
├── bootstrapSubmenuDirective.js
└── submenuTrigger.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | temp/
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/.jshintignore:
--------------------------------------------------------------------------------
1 | lib/
--------------------------------------------------------------------------------
/Code:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlangton/ng-bootstrap-submenu/018446fd1d6ade5fb5eb6b2aea7043c52c4112df/Code
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Ryan Langton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ng-bootstrap-submenu
2 |
3 | Demo: plnkr
4 |
5 | * ng-bootstrap-submenu.min.css
6 | * ng-bootstrap-submenu.min.js
7 |
8 | Add the bootstrapSubmenu module dependency.
9 |
10 | angular.module('myApp', ['bootstrapSubmenu']);
11 |
12 | Use the directive (with ng-repeat if you have multiple dropdowns). Set the menu-item attribute to an object with the following properties:
13 |
14 | * href = the link for the item (only necessary for items with no children).
15 | * display = the text displayed for the item.
16 | * children = an array of sub-items (may be empty).
17 |
18 | Html:
19 |
20 |
21 |
22 |
32 |
33 |
39 |
40 |
41 |
42 | Javascript:
43 |
44 | angular.module('myApp', ['bootstrapSubmenu']);
45 |
46 | angular
47 | .module('myApp')
48 | .controller('menuController', menuController);
49 |
50 | function menuController() {
51 | var vm = this;
52 | vm.menuItems = [
53 | { display: 'Dropdown Item 1', href: '#', children: [
54 | { display: 'Child 1', href: '#', children: [
55 | { display: 'Sub 1', href: '#sub1', children: []},
56 | { display: 'Sub 2', href: '#sub2', children: []}]},
57 | { display: 'Child 2', href: '#child2', children: []}]},
58 | { display: 'Dropdown Item 2', href: '#dropdown2', children: []},
59 | { display: 'Dropdown Item 3', href: '#', children: [
60 | { display: 'Child 3', href: '#child3', children: []}]}
61 | ];
62 | });
--------------------------------------------------------------------------------
/dist/ng-bootstrap-submenu.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
3 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
4 | * Licensed under the MIT license
5 | */
6 |
7 | .dropdown-submenu > a:after {
8 | content: "";
9 | }
10 | @media (min-width: 768px) {
11 | .dropdown-submenu {
12 | position: relative;
13 | }
14 | .dropdown-submenu .dropdown-menu {
15 | top: 0;
16 | left: 100%;
17 | margin-top: -6px;
18 | border-top-left-radius: 0;
19 | }
20 | .dropup .dropdown-submenu .dropdown-menu,
21 | .navbar-fixed-bottom .dropdown-submenu .dropdown-menu {
22 | top: auto;
23 | bottom: 0;
24 | margin-top: 0;
25 | margin-bottom: -6px;
26 | border-top-left-radius: 4px;
27 | border-bottom-left-radius: 0;
28 | }
29 | .dropdown-menu-right .dropdown-submenu .dropdown-menu {
30 | left: auto;
31 | right: 100%;
32 | border-top-left-radius: 4px;
33 | border-top-right-radius: 0;
34 | }
35 | .dropup .dropdown-menu-right .dropdown-submenu .dropdown-menu,
36 | .navbar-fixed-bottom .dropdown-menu-right .dropdown-submenu .dropdown-menu {
37 | border-radius: 4px 4px 0;
38 | }
39 | .dropdown-submenu > a:after {
40 | float: right;
41 | margin-top: 6px;
42 | margin-right: -10px;
43 | border-left: 4px dashed;
44 | border-top: 4px solid transparent;
45 | border-bottom: 4px solid transparent;
46 | }
47 | .dropdown-menu-right .dropdown-submenu > a:after {
48 | float: left;
49 | border-left: none;
50 | margin-left: -10px;
51 | margin-right: 0;
52 | border-right: 4px dashed;
53 | border-top: 4px solid transparent;
54 | border-bottom: 4px solid transparent;
55 | }
56 | }
57 | @media (max-width: 767px) {
58 | .dropdown-submenu .dropdown-menu {
59 | position: static;
60 | margin-top: 0;
61 | border: 0;
62 | box-shadow: none;
63 | }
64 | .dropdown-submenu > a:after {
65 | margin-left: 6px;
66 | display: inline-block;
67 | vertical-align: middle;
68 | border-top: 4px dashed;
69 | border-left: 4px solid transparent;
70 | border-right: 4px solid transparent;
71 | }
72 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
73 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
74 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
75 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a,
76 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a,
77 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a {
78 | padding-left: 30px;
79 | }
80 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
81 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
82 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
83 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a,
84 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a,
85 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a {
86 | padding-left: 40px;
87 | }
88 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
89 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
90 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
91 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
92 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
93 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
94 | padding-left: 50px;
95 | }
96 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
97 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
98 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
99 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
100 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
101 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
102 | padding-left: 60px;
103 | }
104 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
105 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a {
106 | padding-left: 35px;
107 | }
108 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
109 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a {
110 | padding-left: 45px;
111 | }
112 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
113 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
114 | padding-left: 55px;
115 | }
116 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
117 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
118 | padding-left: 65px;
119 | }
120 | }
121 | /*# sourceMappingURL=bootstrap-submenu.css.map */
--------------------------------------------------------------------------------
/dist/ng-bootstrap-submenu.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/bootstrap-submenu.less","less/mixins.less"],"names":[],"mappings":"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","sourcesContent":["// :after: friends with IE8. Use ::after in future.\n\n@import \"../node_modules/bootstrap/less/variables.less\";\n@import \"mixins.less\";\n\n// Variables\n@caret-margin: -@caret-width-base * 2 - 2;\n\n//\n// Sub-Menus\n// --------------------------------------------------\n\n.dropdown-submenu > a:after {\n content: \"\";\n}\n\n@media (min-width: @grid-float-breakpoint) {\n .dropdown-submenu {\n position: relative;\n\n .dropdown-menu {\n top: 0;\n left: 100%;\n margin-top: -6px;\n border-top-left-radius: 0;\n\n // Strictly before .dropdown-menu-right\n .dropup &,\n .navbar-fixed-bottom & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: -6px;\n border-top-left-radius: @border-radius-base;\n border-bottom-left-radius: 0;\n }\n\n .dropdown-menu-right & {\n left: auto;\n right: 100%;\n\n border-top-left-radius: @border-radius-base;\n border-top-right-radius: 0;\n\n .dropup &,\n .navbar-fixed-bottom & {\n border-radius: @border-radius-base @border-radius-base 0;\n }\n }\n }\n\n > a:after {\n float: right;\n margin-top: @line-height-computed / 2 - @caret-width-base;\n margin-right: @caret-margin;\n\n .make-caret(left, top, bottom);\n\n .dropdown-menu-right & {\n float: left;\n border-left: none;\n margin-left: @caret-margin;\n margin-right: 0;\n\n .make-caret(right, top, bottom);\n }\n }\n }\n}\n\n@media (max-width: @grid-float-breakpoint-max) {\n .dropdown-submenu {\n .dropdown-menu {\n position: static;\n margin-top: 0;\n border: 0;\n box-shadow: none;\n }\n\n > a:after {\n margin-left: 6px;\n display: inline-block;\n vertical-align: middle;\n\n .make-caret(top, left, right);\n }\n }\n\n .dropdown-menu > .dropdown-submenu {\n .dropdown > &,\n .dropup > &,\n .btn-group > & {\n .make-nested-list(30px, 0, 4);\n }\n\n .navbar-nav > .dropdown > & {\n .make-nested-list(35px, 0, 4);\n }\n }\n}\n",".make-caret(@base, @left, @right) {\n // dashed: fix caret size for Mozilla Firefox\n border-@{base}: @caret-width-base dashed;\n\n border-@{left}: @caret-width-base solid transparent;\n border-@{right}: @caret-width-base solid transparent;\n}\n\n.make-nested-list(@offset, @i, @n) when (@i < @n) {\n > .dropdown-menu > li {\n &.dropdown-header,\n > a {\n padding-left: @offset + (10 * @i);\n }\n\n .make-nested-list(@offset, @i + 1, @n);\n }\n}\n"]}
--------------------------------------------------------------------------------
/dist/ng-bootstrap-submenu.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | angular.module('bootstrapSubmenu', []);
3 | })();
4 | (function(){
5 | bootstrapSubmenuController.$inject = ["$scope", "submenuTrigger"];
6 | angular
7 | .module('bootstrapSubmenu')
8 | .controller('bootstrapSubmenuController', bootstrapSubmenuController);
9 |
10 | function bootstrapSubmenuController($scope, submenuTrigger){
11 | submenuTrigger.trigger();
12 |
13 | $scope.getDropdownClass = function(){
14 | if (!$scope.hasChildren()) return '';
15 | return $scope.isSubMenu ? 'dropdown-submenu': 'dropdown';
16 | };
17 |
18 | $scope.showCaret = function(){
19 | return (!$scope.isSubMenu && $scope.hasChildren());
20 | };
21 |
22 | $scope.hasChildren = function(){
23 | return ($scope.menuItem.children !== undefined && $scope.menuItem.children.length > 0);
24 | };
25 | }
26 | })();
27 | (function(){
28 | bootstrapSubmenu.$inject = ["$compile"];
29 | angular
30 | .module('bootstrapSubmenu')
31 | .directive('bootstrapSubmenu', bootstrapSubmenu);
32 |
33 | function bootstrapSubmenu($compile) {
34 | return {
35 | restrict: 'E',
36 | scope: {
37 | menuItem: '=menuItem',
38 | isSubMenu: '@isSubMenu'
39 | },
40 | replace: true,
41 | templateUrl: 'bootstrapSubmenu.html',
42 | controller: 'bootstrapSubmenuController',
43 | compile: function (el) {
44 | var contents = el.contents().remove();
45 | var compiled;
46 | return function(scope,el){
47 | if(!compiled)
48 | compiled = $compile(contents);
49 |
50 | compiled(scope,function(clone){
51 | el.append(clone);
52 | });
53 | };
54 | }
55 | };
56 | }
57 | })();
58 | (function(){
59 | submenuTrigger.$inject = ["$timeout"];
60 | angular
61 | .module('bootstrapSubmenu')
62 | .factory('submenuTrigger', submenuTrigger);
63 |
64 | function submenuTrigger($timeout){
65 | var triggered = false;
66 |
67 | return {
68 | trigger: function(){
69 | if (triggered) return;
70 |
71 | // after angularjs digest, trigger submenupicker
72 | $timeout(function(){
73 | $('[data-submenu]').submenupicker();
74 | }, 100);
75 | }
76 | };
77 | }
78 | })();
79 | angular.module("bootstrapSubmenu").run(["$templateCache", function($templateCache) {$templateCache.put("bootstrapSubmenu.html","\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n");}]);
80 | /*!
81 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
82 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
83 | * Licensed under the MIT license
84 | */
85 |
86 | /**
87 | * $.inArray: friends with IE8. Use Array.prototype.indexOf in future.
88 | * $.proxy: friends with IE8. Use Function.prototype.bind in future.
89 | */
90 |
91 | 'use strict';
92 |
93 | (function(factory) {
94 | if (typeof define == 'function' && define.amd) {
95 | // AMD. Register as an anonymous module
96 | define(['jquery'], factory);
97 | }
98 | else if (typeof exports == 'object') {
99 | // Node/CommonJS
100 | module.exports = factory(require('jquery'));
101 | }
102 | else {
103 | // Browser globals
104 | factory(jQuery);
105 | }
106 | })(function($) {
107 | function Item(element) {
108 | this.$element = $(element);
109 | this.$menu = this.$element.closest('.dropdown-menu');
110 | this.$main = this.$menu.parent();
111 | this.$items = this.$menu.children('.dropdown-submenu');
112 |
113 | this.init();
114 | }
115 |
116 | Item.prototype = {
117 | init: function() {
118 | this.$element.on('keydown', $.proxy(this, 'keydown'));
119 | },
120 | close: function() {
121 | this.$main.removeClass('open');
122 | this.$items.trigger('hide.bs.submenu');
123 | },
124 | keydown: function(event) {
125 | // 27: Esc
126 |
127 | if (event.keyCode == 27) {
128 | event.stopPropagation();
129 |
130 | this.close();
131 | this.$main.children('a, button').trigger('focus');
132 | }
133 | }
134 | };
135 |
136 | function SubmenuItem(element) {
137 | this.$element = $(element);
138 | this.$main = this.$element.parent();
139 | this.$menu = this.$main.children('.dropdown-menu');
140 | this.$subs = this.$main.siblings('.dropdown-submenu');
141 | this.$items = this.$menu.children('.dropdown-submenu');
142 |
143 | this.init();
144 | }
145 |
146 | $.extend(SubmenuItem.prototype, Item.prototype, {
147 | init: function() {
148 | this.$element.on({
149 | click: $.proxy(this, 'click'),
150 | keydown: $.proxy(this, 'keydown')
151 | });
152 |
153 | this.$main.on('hide.bs.submenu', $.proxy(this, 'hide'));
154 | },
155 | click: function(event) {
156 | event.stopPropagation();
157 |
158 | this.toggle();
159 | },
160 | hide: function(event) {
161 | // Stop event bubbling
162 | event.stopPropagation();
163 |
164 | this.close();
165 | },
166 | open: function() {
167 | this.$main.addClass('open');
168 | this.$subs.trigger('hide.bs.submenu');
169 | },
170 | toggle: function() {
171 | if (this.$main.hasClass('open')) {
172 | this.close();
173 | }
174 | else {
175 | this.open();
176 | }
177 | },
178 | keydown: function(event) {
179 | // 13: Return, 32: Spacebar
180 |
181 | if (event.keyCode == 32) {
182 | // Off vertical scrolling
183 | event.preventDefault();
184 | }
185 |
186 | if ($.inArray(event.keyCode, [13, 32]) != -1) {
187 | this.toggle();
188 | }
189 | }
190 | });
191 |
192 | function Submenupicker(element) {
193 | this.$element = $(element);
194 | this.$main = this.$element.parent();
195 | this.$menu = this.$main.children('.dropdown-menu');
196 | this.$items = this.$menu.children('.dropdown-submenu');
197 |
198 | this.init();
199 | }
200 |
201 | Submenupicker.prototype = {
202 | init: function() {
203 | this.$menu.off('keydown.bs.dropdown.data-api');
204 | this.$menu.on('keydown', $.proxy(this, 'itemKeydown'));
205 |
206 | this.$menu.find('li > a').each(function() {
207 | new Item(this);
208 | });
209 |
210 | this.$menu.find('.dropdown-submenu > a').each(function() {
211 | new SubmenuItem(this);
212 | });
213 |
214 | this.$main.on('hidden.bs.dropdown', $.proxy(this, 'hidden'));
215 | },
216 | hidden: function() {
217 | this.$items.trigger('hide.bs.submenu');
218 | },
219 | itemKeydown: function(event) {
220 | // 38: Arrow up, 40: Arrow down
221 |
222 | if ($.inArray(event.keyCode, [38, 40]) != -1) {
223 | // Off vertical scrolling
224 | event.preventDefault();
225 |
226 | event.stopPropagation();
227 |
228 | var $items = this.$menu.find('li:not(.disabled):visible > a');
229 | var index = $items.index(event.target);
230 |
231 | if (event.keyCode == 38 && index !== 0) {
232 | index--;
233 | }
234 | else if (event.keyCode == 40 && index !== $items.length - 1) {
235 | index++;
236 | }
237 | else {
238 | return;
239 | }
240 |
241 | $items.eq(index).trigger('focus');
242 | }
243 | }
244 | };
245 |
246 | // For AMD/Node/CommonJS used elements (optional)
247 | // http://learn.jquery.com/jquery-ui/environments/amd/
248 | return $.fn.submenupicker = function(elements) {
249 | var $elements = this instanceof $ ? this : $(elements);
250 |
251 | return $elements.each(function() {
252 | var data = $.data(this, 'bs.submenu');
253 |
254 | if (!data) {
255 | data = new Submenupicker(this);
256 |
257 | $.data(this, 'bs.submenu', data);
258 | }
259 | });
260 | };
261 | });
262 |
--------------------------------------------------------------------------------
/dist/ng-bootstrap-submenu.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
3 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
4 | * Licensed under the MIT license
5 | */
6 |
7 | .dropdown-submenu>a:after{content:""}@media (min-width:768px){.dropdown-submenu{position:relative}.dropdown-submenu .dropdown-menu{top:0;left:100%;margin-top:-6px;border-top-left-radius:0}.dropup .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .dropdown-submenu .dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-6px;border-top-left-radius:4px;border-bottom-left-radius:0}.dropdown-menu-right .dropdown-submenu .dropdown-menu{left:auto;right:100%;border-top-left-radius:4px;border-top-right-radius:0}.dropup .dropdown-menu-right .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .dropdown-menu-right .dropdown-submenu .dropdown-menu{border-radius:4px 4px 0}.dropdown-submenu>a:after{float:right;margin-top:6px;margin-right:-10px;border-left:4px dashed;border-top:4px solid transparent;border-bottom:4px solid transparent}.dropdown-menu-right .dropdown-submenu>a:after{float:left;border-left:none;margin-left:-10px;margin-right:0;border-right:4px dashed;border-top:4px solid transparent;border-bottom:4px solid transparent}}@media (max-width:767px){.dropdown-submenu .dropdown-menu{position:static;margin-top:0;border:0;box-shadow:none}.dropdown-submenu>a:after{margin-left:6px;display:inline-block;vertical-align:middle;border-top:4px dashed;border-left:4px solid transparent;border-right:4px solid transparent}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a{padding-left:30px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:40px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:50px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:60px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a{padding-left:35px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:45px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:55px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:65px}}
8 | /*# sourceMappingURL=bootstrap-submenu.min.css.map */
--------------------------------------------------------------------------------
/dist/ng-bootstrap-submenu.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/bootstrap-submenu.less","less/mixins.less"],"names":[],"mappings":"AAYqB,0BACnB,QAAA,GAGyC,yBACzC,kBACE,SAAA,SAEA,iCACE,IAAA,EACA,KAAA,KACA,WAAA,KACA,uBAAA,EAJF,yCAAA,sDASI,IAAA,KACA,OAAA,EACA,WAAA,EACA,cAAA,KACA,uBAAA,IACA,0BAAA,EAdJ,sDAkBI,KAAA,KACA,MAAA,KAEA,uBAAA,IACA,wBAAA,EAtBJ,8DAAA,2EA0BM,cAAA,IAAA,IAAA,EAKH,0BACD,MAAA,MACA,WAAA,IACA,aAAA,MCpDJ,YAAA,IAAA,OAEA,WAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,YD8CK,+CAQC,MAAA,KACA,YAAA,KACA,YAAA,MACA,aAAA,EC5DN,aAAA,IAAA,OAEA,WAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,aDiE6C,yBAE3C,iCACE,SAAA,OACA,WAAA,EACA,OAAA,EACA,WAAA,KAGC,0BACD,YAAA,IACA,QAAA,aACA,eAAA,OChFJ,WAAA,IAAA,OAEA,YAAA,IAAA,MAAA,YACA,aAAA,IAAA,MAAA,YAKG,8EACD,gEADC,6EACD,+DADC,2EACD,6DACE,aAAA,KAFD,gGACD,kFADC,+FACD,iFADC,6FACD,+EACE,aAAA,KAFD,kHACD,oGADC,iHACD,mGADC,+GACD,iGACE,aAAA,KAFD,oIACD,sHADC,mIACD,qHADC,iIACD,mHACE,aAAA,KAFD,yFACD,2EACE,aAAA,KAFD,2GACD,6FACE,aAAA,KAFD,6HACD,+GACE,aAAA,KAFD,+IACD,iIACE,aAAA"}
--------------------------------------------------------------------------------
/dist/ng-bootstrap-submenu.min.js:
--------------------------------------------------------------------------------
1 | !function(){angular.module("bootstrapSubmenu",[])}(),function(){function n(n,e){e.trigger(),n.getDropdownClass=function(){return n.hasChildren()?n.isSubMenu?"dropdown-submenu":"dropdown":""},n.showCaret=function(){return!n.isSubMenu&&n.hasChildren()},n.hasChildren=function(){return void 0!==n.menuItem.children&&n.menuItem.children.length>0}}n.$inject=["$scope","submenuTrigger"],angular.module("bootstrapSubmenu").controller("bootstrapSubmenuController",n)}(),function(){function n(n){return{restrict:"E",scope:{menuItem:"=menuItem",isSubMenu:"@isSubMenu"},replace:!0,templateUrl:"bootstrapSubmenu.html",controller:"bootstrapSubmenuController",compile:function(e){var t,i=e.contents().remove();return function(e,o){t||(t=n(i)),t(e,function(n){o.append(n)})}}}}n.$inject=["$compile"],angular.module("bootstrapSubmenu").directive("bootstrapSubmenu",n)}(),function(){function n(n){var e=!1;return{trigger:function(){e||n(function(){$("[data-submenu]").submenupicker()},100)}}}n.$inject=["$timeout"],angular.module("bootstrapSubmenu").factory("submenuTrigger",n)}(),angular.module("bootstrapSubmenu").run(["$templateCache",function(n){n.put("bootstrapSubmenu.html",'\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n')}]),function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof exports?module.exports=n(require("jquery")):n(jQuery)}(function(n){function e(e){this.$element=n(e),this.$menu=this.$element.closest(".dropdown-menu"),this.$main=this.$menu.parent(),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}function t(e){this.$element=n(e),this.$main=this.$element.parent(),this.$menu=this.$main.children(".dropdown-menu"),this.$subs=this.$main.siblings(".dropdown-submenu"),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}function i(e){this.$element=n(e),this.$main=this.$element.parent(),this.$menu=this.$main.children(".dropdown-menu"),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}return e.prototype={init:function(){this.$element.on("keydown",n.proxy(this,"keydown"))},close:function(){this.$main.removeClass("open"),this.$items.trigger("hide.bs.submenu")},keydown:function(n){27==n.keyCode&&(n.stopPropagation(),this.close(),this.$main.children("a, button").trigger("focus"))}},n.extend(t.prototype,e.prototype,{init:function(){this.$element.on({click:n.proxy(this,"click"),keydown:n.proxy(this,"keydown")}),this.$main.on("hide.bs.submenu",n.proxy(this,"hide"))},click:function(n){n.stopPropagation(),this.toggle()},hide:function(n){n.stopPropagation(),this.close()},open:function(){this.$main.addClass("open"),this.$subs.trigger("hide.bs.submenu")},toggle:function(){this.$main.hasClass("open")?this.close():this.open()},keydown:function(e){32==e.keyCode&&e.preventDefault(),n.inArray(e.keyCode,[13,32])!=-1&&this.toggle()}}),i.prototype={init:function(){this.$menu.off("keydown.bs.dropdown.data-api"),this.$menu.on("keydown",n.proxy(this,"itemKeydown")),this.$menu.find("li > a").each(function(){new e(this)}),this.$menu.find(".dropdown-submenu > a").each(function(){new t(this)}),this.$main.on("hidden.bs.dropdown",n.proxy(this,"hidden"))},hidden:function(){this.$items.trigger("hide.bs.submenu")},itemKeydown:function(e){if(n.inArray(e.keyCode,[38,40])!=-1){e.preventDefault(),e.stopPropagation();var t=this.$menu.find("li:not(.disabled):visible > a"),i=t.index(e.target);if(38==e.keyCode&&0!==i)i--;else{if(40!=e.keyCode||i===t.length-1)return;i++}t.eq(i).trigger("focus")}}},n.fn.submenupicker=function(e){var t=this instanceof n?this:n(e);return t.each(function(){var e=n.data(this,"bs.submenu");e||(e=new i(this),n.data(this,"bs.submenu",e))})}});
--------------------------------------------------------------------------------
/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
26 |
27 |
33 |
34 |
35 |
60 |
61 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var gulp = require('gulp');
4 | var templateCache = require('gulp-angular-templatecache');
5 | var concat = require('gulp-concat');
6 | var jshint = require('gulp-jshint');
7 | var ngAnnotate = require('gulp-ng-annotate');
8 | var rename = require("gulp-rename");
9 | var rimraf = require('gulp-rimraf');
10 | var uglify = require('gulp-uglify');
11 | var gutil = require('gulp-util');
12 |
13 | var config = {
14 | paths: {
15 | bootstrapSubmenuCss: './lib/bootstrap-submenu-2.0.1-dist/css/*.*',
16 | bootstrapSubmenuJs: './lib/bootstrap-submenu-2.0.1-dist/js/bootstrap-submenu.js',
17 | html: './src/*.html',
18 | js: './src/*.js',
19 | dist: './dist',
20 | temp: './temp'
21 | }
22 | }
23 |
24 | gulp.task('clean', function(){
25 | return gulp.src([config.paths.temp, config.paths.dist], {read: false})
26 | .pipe(rimraf());
27 | });
28 |
29 | gulp.task('css', ['clean'], function() {
30 | return gulp.src(config.paths.bootstrapSubmenuCss)
31 | .pipe(rename({
32 | prefix: "ng-"
33 | }))
34 | .pipe(gulp.dest(config.paths.dist));
35 | });
36 |
37 | gulp.task('html', ['clean'], function() {
38 | return gulp.src(config.paths.html)
39 | .pipe(templateCache({
40 | module: 'bootstrapSubmenu'
41 | }))
42 | .pipe(gulp.dest(config.paths.temp));
43 | });
44 |
45 | gulp.task('minjs', ['html', 'clean'], function() {
46 | return gulp.src([config.paths.js, config.paths.temp + '/*.js', config.paths.bootstrapSubmenuJs])
47 | .pipe(jshint())
48 | .pipe(jshint.reporter('default'))
49 | .pipe(ngAnnotate())
50 | .pipe(concat('ng-bootstrap-submenu.min.js'))
51 | .pipe(uglify().on('error', gutil.log))
52 | .pipe(gulp.dest(config.paths.dist));
53 | });
54 |
55 | gulp.task('js', ['html', 'clean'], function() {
56 | return gulp.src([config.paths.js, config.paths.temp + '/*.js', config.paths.bootstrapSubmenuJs])
57 | .pipe(jshint())
58 | .pipe(jshint.reporter('default'))
59 | .pipe(ngAnnotate())
60 | .pipe(concat('ng-bootstrap-submenu.js'))
61 | .pipe(gulp.dest(config.paths.dist));
62 | });
63 |
64 | gulp.task('default', ['html', 'js', 'minjs', 'css', 'clean']);
--------------------------------------------------------------------------------
/lib/bootstrap-submenu-2.0.1-dist/css/bootstrap-submenu.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
3 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
4 | * Licensed under the MIT license
5 | */
6 |
7 | .dropdown-submenu > a:after {
8 | content: "";
9 | }
10 | @media (min-width: 768px) {
11 | .dropdown-submenu {
12 | position: relative;
13 | }
14 | .dropdown-submenu .dropdown-menu {
15 | top: 0;
16 | left: 100%;
17 | margin-top: -6px;
18 | border-top-left-radius: 0;
19 | }
20 | .dropup .dropdown-submenu .dropdown-menu,
21 | .navbar-fixed-bottom .dropdown-submenu .dropdown-menu {
22 | top: auto;
23 | bottom: 0;
24 | margin-top: 0;
25 | margin-bottom: -6px;
26 | border-top-left-radius: 4px;
27 | border-bottom-left-radius: 0;
28 | }
29 | .dropdown-menu-right .dropdown-submenu .dropdown-menu {
30 | left: auto;
31 | right: 100%;
32 | border-top-left-radius: 4px;
33 | border-top-right-radius: 0;
34 | }
35 | .dropup .dropdown-menu-right .dropdown-submenu .dropdown-menu,
36 | .navbar-fixed-bottom .dropdown-menu-right .dropdown-submenu .dropdown-menu {
37 | border-radius: 4px 4px 0;
38 | }
39 | .dropdown-submenu > a:after {
40 | float: right;
41 | margin-top: 6px;
42 | margin-right: -10px;
43 | border-left: 4px dashed;
44 | border-top: 4px solid transparent;
45 | border-bottom: 4px solid transparent;
46 | }
47 | .dropdown-menu-right .dropdown-submenu > a:after {
48 | float: left;
49 | border-left: none;
50 | margin-left: -10px;
51 | margin-right: 0;
52 | border-right: 4px dashed;
53 | border-top: 4px solid transparent;
54 | border-bottom: 4px solid transparent;
55 | }
56 | }
57 | @media (max-width: 767px) {
58 | .dropdown-submenu .dropdown-menu {
59 | position: static;
60 | margin-top: 0;
61 | border: 0;
62 | box-shadow: none;
63 | }
64 | .dropdown-submenu > a:after {
65 | margin-left: 6px;
66 | display: inline-block;
67 | vertical-align: middle;
68 | border-top: 4px dashed;
69 | border-left: 4px solid transparent;
70 | border-right: 4px solid transparent;
71 | }
72 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
73 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
74 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
75 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a,
76 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a,
77 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a {
78 | padding-left: 30px;
79 | }
80 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
81 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
82 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
83 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a,
84 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a,
85 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a {
86 | padding-left: 40px;
87 | }
88 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
89 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
90 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
91 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
92 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
93 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
94 | padding-left: 50px;
95 | }
96 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
97 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
98 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
99 | .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
100 | .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,
101 | .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
102 | padding-left: 60px;
103 | }
104 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header,
105 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a {
106 | padding-left: 35px;
107 | }
108 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
109 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a {
110 | padding-left: 45px;
111 | }
112 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
113 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
114 | padding-left: 55px;
115 | }
116 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header,
117 | .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a {
118 | padding-left: 65px;
119 | }
120 | }
121 | /*# sourceMappingURL=bootstrap-submenu.css.map */
--------------------------------------------------------------------------------
/lib/bootstrap-submenu-2.0.1-dist/css/bootstrap-submenu.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/bootstrap-submenu.less","less/mixins.less"],"names":[],"mappings":"AAYA,iBAAkB,IAAG;EACnB,SAAS,EAAT;;AAyDF,QAtD2C;EACzC;IACE,kBAAA;;EADF,iBAGE;IACE,MAAA;IACA,UAAA;IACA,gBAAA;IACA,yBAAA;;EAGA,OAAQ,kBAPV;EAQE,oBAAqB,kBARvB;IASI,SAAA;IACA,SAAA;IACA,aAAA;IACA,mBAAA;IACA,2BAAA;IACA,4BAAA;;EAGF,oBAAqB,kBAjBvB;IAkBI,UAAA;IACA,WAAA;IAEA,2BAAA;IACA,0BAAA;;EAEA,OAAQ,qBAPW,kBAjBvB;EAyBI,oBAAqB,qBARF,kBAjBvB;IA0BM,wBAAA;;EA7BR,iBAkCE,IAAG;IACD,YAAA;IACA,eAAA;IACA,mBAAA;ICpDJ,uBAAA;IAEA,iCAAA;IACA,oCAAA;;EDqDI,oBAAqB,kBAPvB,IAAG;IAQC,WAAA;IACA,iBAAA;IACA,kBAAA;IACA,eAAA;IC5DN,wBAAA;IAEA,iCAAA;IACA,oCAAA;;;AD+FF,QA9B+C;EAC7C,iBACE;IACE,gBAAA;IACA,aAAA;IACA,SAAA;IACA,gBAAA;;EALJ,iBAQE,IAAG;IACD,gBAAA;IACA,qBAAA;IACA,sBAAA;IChFJ,sBAAA;IAEA,kCAAA;IACA,mCAAA;;EAKE,SD+EU,iBADG,oBC/Ef,iBAAiB,KACd;EAAD,ODgFQ,iBAFK,oBC/Ef,iBAAiB,KACd;EAAD,UDiFW,iBAHE,oBC/Ef,iBAAiB,KACd;ED+ED,SAAU,iBADG,oBC/Ef,iBAAiB,KAEf;ED+EA,OAAQ,iBAFK,oBC/Ef,iBAAiB,KAEf;EDgFA,UAAW,iBAHE,oBC/Ef,iBAAiB,KAEf;IACE,kBAAA;;EAFF,SD+EU,iBADG,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,ODgFQ,iBAFK,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,UDiFW,iBAHE,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KACd;ED+ED,SAAU,iBADG,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAEf;ED+EA,OAAQ,iBAFK,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAEf;EDgFA,UAAW,iBAHE,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,SD+EU,iBADG,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,ODgFQ,iBAFK,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,UDiFW,iBAHE,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;ED+ED,SAAU,iBADG,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;ED+EA,OAAQ,iBAFK,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;EDgFA,UAAW,iBAHE,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,SD+EU,iBADG,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,ODgFQ,iBAFK,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,UDiFW,iBAHE,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;ED+ED,SAAU,iBADG,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;ED+EA,OAAQ,iBAFK,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;EDgFA,UAAW,iBAHE,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDqFY,YAAY,iBAPX,oBC/Ef,iBAAiB,KACd;EDqFD,WAAY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDqFY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KACd;EDqFD,WAAY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDqFY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EDqFD,WAAY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDqFY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EDqFD,WAAY,YAAY,iBAPX,oBC/Ef,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA","sourcesContent":["// :after: friends with IE8. Use ::after in future.\n\n@import \"../node_modules/bootstrap/less/variables.less\";\n@import \"mixins.less\";\n\n// Variables\n@caret-margin: -@caret-width-base * 2 - 2;\n\n//\n// Sub-Menus\n// --------------------------------------------------\n\n.dropdown-submenu > a:after {\n content: \"\";\n}\n\n@media (min-width: @grid-float-breakpoint) {\n .dropdown-submenu {\n position: relative;\n\n .dropdown-menu {\n top: 0;\n left: 100%;\n margin-top: -6px;\n border-top-left-radius: 0;\n\n // Strictly before .dropdown-menu-right\n .dropup &,\n .navbar-fixed-bottom & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: -6px;\n border-top-left-radius: @border-radius-base;\n border-bottom-left-radius: 0;\n }\n\n .dropdown-menu-right & {\n left: auto;\n right: 100%;\n\n border-top-left-radius: @border-radius-base;\n border-top-right-radius: 0;\n\n .dropup &,\n .navbar-fixed-bottom & {\n border-radius: @border-radius-base @border-radius-base 0;\n }\n }\n }\n\n > a:after {\n float: right;\n margin-top: @line-height-computed / 2 - @caret-width-base;\n margin-right: @caret-margin;\n\n .make-caret(left, top, bottom);\n\n .dropdown-menu-right & {\n float: left;\n border-left: none;\n margin-left: @caret-margin;\n margin-right: 0;\n\n .make-caret(right, top, bottom);\n }\n }\n }\n}\n\n@media (max-width: @grid-float-breakpoint-max) {\n .dropdown-submenu {\n .dropdown-menu {\n position: static;\n margin-top: 0;\n border: 0;\n box-shadow: none;\n }\n\n > a:after {\n margin-left: 6px;\n display: inline-block;\n vertical-align: middle;\n\n .make-caret(top, left, right);\n }\n }\n\n .dropdown-menu > .dropdown-submenu {\n .dropdown > &,\n .dropup > &,\n .btn-group > & {\n .make-nested-list(30px, 0, 4);\n }\n\n .navbar-nav > .dropdown > & {\n .make-nested-list(35px, 0, 4);\n }\n }\n}\n",".make-caret(@base, @left, @right) {\n // dashed: fix caret size for Mozilla Firefox\n border-@{base}: @caret-width-base dashed;\n\n border-@{left}: @caret-width-base solid transparent;\n border-@{right}: @caret-width-base solid transparent;\n}\n\n.make-nested-list(@offset, @i, @n) when (@i < @n) {\n > .dropdown-menu > li {\n &.dropdown-header,\n > a {\n padding-left: @offset + (10 * @i);\n }\n\n .make-nested-list(@offset, @i + 1, @n);\n }\n}\n"]}
--------------------------------------------------------------------------------
/lib/bootstrap-submenu-2.0.1-dist/css/bootstrap-submenu.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
3 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
4 | * Licensed under the MIT license
5 | */
6 |
7 | .dropdown-submenu>a:after{content:""}@media (min-width:768px){.dropdown-submenu{position:relative}.dropdown-submenu .dropdown-menu{top:0;left:100%;margin-top:-6px;border-top-left-radius:0}.dropup .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .dropdown-submenu .dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-6px;border-top-left-radius:4px;border-bottom-left-radius:0}.dropdown-menu-right .dropdown-submenu .dropdown-menu{left:auto;right:100%;border-top-left-radius:4px;border-top-right-radius:0}.dropup .dropdown-menu-right .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .dropdown-menu-right .dropdown-submenu .dropdown-menu{border-radius:4px 4px 0}.dropdown-submenu>a:after{float:right;margin-top:6px;margin-right:-10px;border-left:4px dashed;border-top:4px solid transparent;border-bottom:4px solid transparent}.dropdown-menu-right .dropdown-submenu>a:after{float:left;border-left:none;margin-left:-10px;margin-right:0;border-right:4px dashed;border-top:4px solid transparent;border-bottom:4px solid transparent}}@media (max-width:767px){.dropdown-submenu .dropdown-menu{position:static;margin-top:0;border:0;box-shadow:none}.dropdown-submenu>a:after{margin-left:6px;display:inline-block;vertical-align:middle;border-top:4px dashed;border-left:4px solid transparent;border-right:4px solid transparent}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a{padding-left:30px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:40px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:50px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:60px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a{padding-left:35px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:45px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:55px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:65px}}
8 | /*# sourceMappingURL=bootstrap-submenu.min.css.map */
--------------------------------------------------------------------------------
/lib/bootstrap-submenu-2.0.1-dist/css/bootstrap-submenu.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/bootstrap-submenu.less","less/mixins.less"],"names":[],"mappings":"AAYqB,0BACnB,QAAA,GAGyC,yBACzC,kBACE,SAAA,SAEA,iCACE,IAAA,EACA,KAAA,KACA,WAAA,KACA,uBAAA,EAJF,yCAAA,sDASI,IAAA,KACA,OAAA,EACA,WAAA,EACA,cAAA,KACA,uBAAA,IACA,0BAAA,EAdJ,sDAkBI,KAAA,KACA,MAAA,KAEA,uBAAA,IACA,wBAAA,EAtBJ,8DAAA,2EA0BM,cAAA,IAAA,IAAA,EAKH,0BACD,MAAA,MACA,WAAA,IACA,aAAA,MCpDJ,YAAA,IAAA,OAEA,WAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,YD8CK,+CAQC,MAAA,KACA,YAAA,KACA,YAAA,MACA,aAAA,EC5DN,aAAA,IAAA,OAEA,WAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,aDiE6C,yBAE3C,iCACE,SAAA,OACA,WAAA,EACA,OAAA,EACA,WAAA,KAGC,0BACD,YAAA,IACA,QAAA,aACA,eAAA,OChFJ,WAAA,IAAA,OAEA,YAAA,IAAA,MAAA,YACA,aAAA,IAAA,MAAA,YAKG,8EACD,gEADC,6EACD,+DADC,2EACD,6DACE,aAAA,KAFD,gGACD,kFADC,+FACD,iFADC,6FACD,+EACE,aAAA,KAFD,kHACD,oGADC,iHACD,mGADC,+GACD,iGACE,aAAA,KAFD,oIACD,sHADC,mIACD,qHADC,iIACD,mHACE,aAAA,KAFD,yFACD,2EACE,aAAA,KAFD,2GACD,6FACE,aAAA,KAFD,6HACD,+GACE,aAAA,KAFD,+IACD,iIACE,aAAA"}
--------------------------------------------------------------------------------
/lib/bootstrap-submenu-2.0.1-dist/js/bootstrap-submenu.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
3 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
4 | * Licensed under the MIT license
5 | */
6 |
7 | /**
8 | * $.inArray: friends with IE8. Use Array.prototype.indexOf in future.
9 | * $.proxy: friends with IE8. Use Function.prototype.bind in future.
10 | */
11 |
12 | 'use strict';
13 |
14 | (function(factory) {
15 | if (typeof define == 'function' && define.amd) {
16 | // AMD. Register as an anonymous module
17 | define(['jquery'], factory);
18 | }
19 | else if (typeof exports == 'object') {
20 | // Node/CommonJS
21 | module.exports = factory(require('jquery'));
22 | }
23 | else {
24 | // Browser globals
25 | factory(jQuery);
26 | }
27 | })(function($) {
28 | function Item(element) {
29 | this.$element = $(element);
30 | this.$menu = this.$element.closest('.dropdown-menu');
31 | this.$main = this.$menu.parent();
32 | this.$items = this.$menu.children('.dropdown-submenu');
33 |
34 | this.init();
35 | }
36 |
37 | Item.prototype = {
38 | init: function() {
39 | this.$element.on('keydown', $.proxy(this, 'keydown'));
40 | },
41 | close: function() {
42 | this.$main.removeClass('open');
43 | this.$items.trigger('hide.bs.submenu');
44 | },
45 | keydown: function(event) {
46 | // 27: Esc
47 |
48 | if (event.keyCode == 27) {
49 | event.stopPropagation();
50 |
51 | this.close();
52 | this.$main.children('a, button').trigger('focus');
53 | }
54 | }
55 | };
56 |
57 | function SubmenuItem(element) {
58 | this.$element = $(element);
59 | this.$main = this.$element.parent();
60 | this.$menu = this.$main.children('.dropdown-menu');
61 | this.$subs = this.$main.siblings('.dropdown-submenu');
62 | this.$items = this.$menu.children('.dropdown-submenu');
63 |
64 | this.init();
65 | }
66 |
67 | $.extend(SubmenuItem.prototype, Item.prototype, {
68 | init: function() {
69 | this.$element.on({
70 | click: $.proxy(this, 'click'),
71 | keydown: $.proxy(this, 'keydown')
72 | });
73 |
74 | this.$main.on('hide.bs.submenu', $.proxy(this, 'hide'));
75 | },
76 | click: function(event) {
77 | event.stopPropagation();
78 |
79 | this.toggle();
80 | },
81 | hide: function(event) {
82 | // Stop event bubbling
83 | event.stopPropagation();
84 |
85 | this.close();
86 | },
87 | open: function() {
88 | this.$main.addClass('open');
89 | this.$subs.trigger('hide.bs.submenu');
90 | },
91 | toggle: function() {
92 | if (this.$main.hasClass('open')) {
93 | this.close();
94 | }
95 | else {
96 | this.open();
97 | }
98 | },
99 | keydown: function(event) {
100 | // 13: Return, 32: Spacebar
101 |
102 | if (event.keyCode == 32) {
103 | // Off vertical scrolling
104 | event.preventDefault();
105 | }
106 |
107 | if ($.inArray(event.keyCode, [13, 32]) != -1) {
108 | this.toggle();
109 | }
110 | }
111 | });
112 |
113 | function Submenupicker(element) {
114 | this.$element = $(element);
115 | this.$main = this.$element.parent();
116 | this.$menu = this.$main.children('.dropdown-menu');
117 | this.$items = this.$menu.children('.dropdown-submenu');
118 |
119 | this.init();
120 | }
121 |
122 | Submenupicker.prototype = {
123 | init: function() {
124 | this.$menu.off('keydown.bs.dropdown.data-api');
125 | this.$menu.on('keydown', $.proxy(this, 'itemKeydown'));
126 |
127 | this.$menu.find('li > a').each(function() {
128 | new Item(this);
129 | });
130 |
131 | this.$menu.find('.dropdown-submenu > a').each(function() {
132 | new SubmenuItem(this);
133 | });
134 |
135 | this.$main.on('hidden.bs.dropdown', $.proxy(this, 'hidden'));
136 | },
137 | hidden: function() {
138 | this.$items.trigger('hide.bs.submenu');
139 | },
140 | itemKeydown: function(event) {
141 | // 38: Arrow up, 40: Arrow down
142 |
143 | if ($.inArray(event.keyCode, [38, 40]) != -1) {
144 | // Off vertical scrolling
145 | event.preventDefault();
146 |
147 | event.stopPropagation();
148 |
149 | var $items = this.$menu.find('li:not(.disabled):visible > a');
150 | var index = $items.index(event.target);
151 |
152 | if (event.keyCode == 38 && index !== 0) {
153 | index--;
154 | }
155 | else if (event.keyCode == 40 && index !== $items.length - 1) {
156 | index++;
157 | }
158 | else {
159 | return;
160 | }
161 |
162 | $items.eq(index).trigger('focus');
163 | }
164 | }
165 | };
166 |
167 | // For AMD/Node/CommonJS used elements (optional)
168 | // http://learn.jquery.com/jquery-ui/environments/amd/
169 | return $.fn.submenupicker = function(elements) {
170 | var $elements = this instanceof $ ? this : $(elements);
171 |
172 | return $elements.each(function() {
173 | var data = $.data(this, 'bs.submenu');
174 |
175 | if (!data) {
176 | data = new Submenupicker(this);
177 |
178 | $.data(this, 'bs.submenu', data);
179 | }
180 | });
181 | };
182 | });
183 |
--------------------------------------------------------------------------------
/lib/bootstrap-submenu-2.0.1-dist/js/bootstrap-submenu.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap-submenu v2.0.1 (http://vsn4ik.github.io/bootstrap-submenu)
3 | * Copyright 2015 Vasily A. (https://github.com/vsn4ik)
4 | * Licensed under the MIT license
5 | */
6 |
7 | "use strict";!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){function b(b){this.$element=a(b),this.$menu=this.$element.closest(".dropdown-menu"),this.$main=this.$menu.parent(),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}function c(b){this.$element=a(b),this.$main=this.$element.parent(),this.$menu=this.$main.children(".dropdown-menu"),this.$subs=this.$main.siblings(".dropdown-submenu"),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}function d(b){this.$element=a(b),this.$main=this.$element.parent(),this.$menu=this.$main.children(".dropdown-menu"),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}return b.prototype={init:function(){this.$element.on("keydown",a.proxy(this,"keydown"))},close:function(){this.$main.removeClass("open"),this.$items.trigger("hide.bs.submenu")},keydown:function(a){27==a.keyCode&&(a.stopPropagation(),this.close(),this.$main.children("a, button").trigger("focus"))}},a.extend(c.prototype,b.prototype,{init:function(){this.$element.on({click:a.proxy(this,"click"),keydown:a.proxy(this,"keydown")}),this.$main.on("hide.bs.submenu",a.proxy(this,"hide"))},click:function(a){a.stopPropagation(),this.toggle()},hide:function(a){a.stopPropagation(),this.close()},open:function(){this.$main.addClass("open"),this.$subs.trigger("hide.bs.submenu")},toggle:function(){this.$main.hasClass("open")?this.close():this.open()},keydown:function(b){32==b.keyCode&&b.preventDefault(),-1!=a.inArray(b.keyCode,[13,32])&&this.toggle()}}),d.prototype={init:function(){this.$menu.off("keydown.bs.dropdown.data-api"),this.$menu.on("keydown",a.proxy(this,"itemKeydown")),this.$menu.find("li > a").each(function(){new b(this)}),this.$menu.find(".dropdown-submenu > a").each(function(){new c(this)}),this.$main.on("hidden.bs.dropdown",a.proxy(this,"hidden"))},hidden:function(){this.$items.trigger("hide.bs.submenu")},itemKeydown:function(b){if(-1!=a.inArray(b.keyCode,[38,40])){b.preventDefault(),b.stopPropagation();var c=this.$menu.find("li:not(.disabled):visible > a"),d=c.index(b.target);if(38==b.keyCode&&0!==d)d--;else{if(40!=b.keyCode||d===c.length-1)return;d++}c.eq(d).trigger("focus")}}},a.fn.submenupicker=function(b){var c=this instanceof a?this:a(b);return c.each(function(){var b=a.data(this,"bs.submenu");b||(b=new d(this),a.data(this,"bs.submenu",b))})}});
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng-bootstrap-submenu",
3 | "version": "1.0.10",
4 | "description": "",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1"
7 | },
8 | "author": "Ryan Langton",
9 | "license": "MIT",
10 | "dependencies": {
11 | "angular": "^1.3.0",
12 | "bootstrap": "^3.3.6"
13 | },
14 | "devDependencies": {
15 | "gulp": "^3.9.0",
16 | "gulp-angular-templatecache": "^1.8.0",
17 | "gulp-concat": "^2.6.0",
18 | "gulp-jshint": "^2.0.0",
19 | "gulp-ng-annotate": "^1.1.0",
20 | "gulp-rename": "^1.2.2",
21 | "gulp-rimraf": "^0.2.0",
22 | "gulp-uglify": "^1.5.1",
23 | "gulp-util": "^3.0.7",
24 | "jshint": "^2.9.2"
25 | },
26 | "files": [
27 | "dist"
28 | ],
29 | "main" :"./dist/ng-bootstrap-submenu.js"
30 | }
31 |
--------------------------------------------------------------------------------
/src/bootstrapSubmenu.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/src/bootstrapSubmenu.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | angular.module('bootstrapSubmenu', []);
3 | })();
--------------------------------------------------------------------------------
/src/bootstrapSubmenuController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | angular
3 | .module('bootstrapSubmenu')
4 | .controller('bootstrapSubmenuController', bootstrapSubmenuController);
5 |
6 | function bootstrapSubmenuController($scope, submenuTrigger){
7 | submenuTrigger.trigger();
8 |
9 | $scope.getDropdownClass = function(){
10 | if (!$scope.hasChildren()) return '';
11 | return $scope.isSubMenu ? 'dropdown-submenu': 'dropdown';
12 | };
13 |
14 | $scope.showCaret = function(){
15 | return (!$scope.isSubMenu && $scope.hasChildren());
16 | };
17 |
18 | $scope.hasChildren = function(){
19 | return ($scope.menuItem.children !== undefined && $scope.menuItem.children.length > 0);
20 | };
21 | }
22 | })();
--------------------------------------------------------------------------------
/src/bootstrapSubmenuDirective.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | angular
3 | .module('bootstrapSubmenu')
4 | .directive('bootstrapSubmenu', bootstrapSubmenu);
5 |
6 | function bootstrapSubmenu($compile) {
7 | return {
8 | restrict: 'E',
9 | scope: {
10 | menuItem: '=menuItem',
11 | isSubMenu: '@isSubMenu'
12 | },
13 | replace: true,
14 | templateUrl: 'bootstrapSubmenu.html',
15 | controller: 'bootstrapSubmenuController',
16 | compile: function (el) {
17 | var contents = el.contents().remove();
18 | var compiled;
19 | return function(scope,el){
20 | if(!compiled)
21 | compiled = $compile(contents);
22 |
23 | compiled(scope,function(clone){
24 | el.append(clone);
25 | });
26 | };
27 | }
28 | };
29 | }
30 | })();
--------------------------------------------------------------------------------
/src/submenuTrigger.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | angular
3 | .module('bootstrapSubmenu')
4 | .factory('submenuTrigger', submenuTrigger);
5 |
6 | function submenuTrigger($timeout){
7 | var triggered = false;
8 |
9 | return {
10 | trigger: function(){
11 | if (triggered) return;
12 |
13 | // after angularjs digest, trigger submenupicker
14 | $timeout(function(){
15 | $('[data-submenu]').submenupicker();
16 | }, 100);
17 | }
18 | };
19 | }
20 | })();
--------------------------------------------------------------------------------