-
Notifications
You must be signed in to change notification settings - Fork 2
/
jquery.smartmenus.bootstrap-4.js
166 lines (153 loc) · 5.78 KB
/
jquery.smartmenus.bootstrap-4.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*!
* SmartMenus jQuery Plugin Bootstrap 4 Addon - v0.1.1 - November 3, 2022
* http://www.smartmenus.org/
*
* Copyright Vasil Dinkov, Vadikom Web Ltd.
* http://vadikom.com
*
* Licensed MIT
*/
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery', 'smartmenus'], factory);
} else if (typeof module === 'object' && typeof module.exports === 'object') {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// Global jQuery
factory(jQuery);
}
} (function($) {
$.extend($.SmartMenus.Bootstrap = {}, {
keydownFix: false,
init: function() {
// init all navbars that don't have the "data-sm-skip" attribute set
var $navbars = $('ul.navbar-nav:not([data-sm-skip])');
$navbars.each(function() {
var $this = $(this),
obj = $this.data('smartmenus');
// if this navbar is not initialized
if (!obj) {
var skipBehavior = $this.is('[data-sm-skip-collapsible-behavior]'),
rightAligned = $this.hasClass('ml-auto') || $this.prevAll('.mr-auto').length > 0;
$this.smartmenus({
// these are some good default options that should work for all
subMenusSubOffsetX: 2,
subMenusSubOffsetY: -9,
subIndicators: !skipBehavior,
collapsibleShowFunction: null,
collapsibleHideFunction: null,
rightToLeftSubMenus: rightAligned,
bottomToTopSubMenus: $this.closest('.fixed-bottom').length > 0,
// custom option(s) for the Bootstrap 4 addon
bootstrapHighlightClasses: 'text-dark bg-light'
})
.on({
// set/unset proper Bootstrap classes for some menu elements
'show.smapi': function(e, menu) {
var $menu = $(menu),
$scrollArrows = $menu.dataSM('scroll-arrows');
if ($scrollArrows) {
$scrollArrows.css('background-color', $menu.css('background-color'));
}
$menu.parent().addClass('show');
if (obj.opts.keepHighlighted && $menu.dataSM('level') > 2) {
$menu.prevAll('a').addClass(obj.opts.bootstrapHighlightClasses);
}
},
'hide.smapi': function(e, menu) {
var $menu = $(menu);
$menu.parent().removeClass('show');
if (obj.opts.keepHighlighted && $menu.dataSM('level') > 2) {
$menu.prevAll('a').removeClass(obj.opts.bootstrapHighlightClasses);
}
}
});
obj = $this.data('smartmenus');
function onInit() {
// set Bootstrap's "active" class to SmartMenus "current" items (should someone decide to enable markCurrentItem: true)
$this.find('a.current').each(function() {
var $this = $(this);
// dropdown items require the class to be set to the A's while for nav items it should be set to the parent LI's
($this.hasClass('dropdown-item') ? $this : $this.parent()).addClass('active');
});
// parent items fixes
$this.find('a.has-submenu').each(function() {
var $this = $(this);
// remove Bootstrap required attributes that might cause conflicting issues with the SmartMenus script
if ($this.is('[data-toggle="dropdown"]')) {
$this.dataSM('bs-data-toggle-dropdown', true).removeAttr('data-toggle');
}
// remove Bootstrap's carets generating class
if (!skipBehavior && $this.hasClass('dropdown-toggle')) {
$this.dataSM('bs-dropdown-toggle', true).removeClass('dropdown-toggle');
}
});
}
onInit();
function onBeforeDestroy() {
$this.find('a.current').each(function() {
var $this = $(this);
($this.hasClass('active') ? $this : $this.parent()).removeClass('active');
});
$this.find('a.has-submenu').each(function() {
var $this = $(this);
if ($this.dataSM('bs-dropdown-toggle')) {
$this.addClass('dropdown-toggle').removeDataSM('bs-dropdown-toggle');
}
if ($this.dataSM('bs-data-toggle-dropdown')) {
$this.attr('data-toggle', 'dropdown').removeDataSM('bs-data-toggle-dropdown');
}
});
}
// custom "refresh" method for Bootstrap
obj.refresh = function() {
$.SmartMenus.prototype.refresh.call(this);
onInit();
// update collapsible detection
detectCollapsible(true);
};
// custom "destroy" method for Bootstrap
obj.destroy = function(refresh) {
onBeforeDestroy();
$.SmartMenus.prototype.destroy.call(this, refresh);
};
// keep Bootstrap's default behavior (i.e. use the whole item area just as a sub menu toggle)
if (skipBehavior) {
obj.opts.collapsibleBehavior = 'toggle';
}
// onresize detect when the navbar becomes collapsible and add it the "sm-collapsible" class
var winW;
function detectCollapsible(force) {
var newW = obj.getViewportWidth();
if (newW != winW || force) {
if (obj.isCollapsible()) {
$this.addClass('sm-collapsible');
} else {
$this.removeClass('sm-collapsible');
}
winW = newW;
}
}
detectCollapsible();
$(window).on('resize.smartmenus' + obj.rootId, detectCollapsible);
}
});
// keydown fix for Bootstrap 4 conflict
if ($navbars.length && !$.SmartMenus.Bootstrap.keydownFix) {
// unhook BS keydown handler for all dropdowns
$(document).off('keydown.bs.dropdown.data-api', '.dropdown-menu');
// restore BS keydown handler for dropdowns that are not inside SmartMenus navbars
// SmartMenus won't add the "show" class so it's handy here
if ($.fn.dropdown && $.fn.dropdown.Constructor && typeof $.fn.dropdown.Constructor._dataApiKeydownHandler == 'function') {
$(document).on('keydown.bs.dropdown.data-api', '.dropdown-menu.show', $.fn.dropdown.Constructor._dataApiKeydownHandler);
}
$.SmartMenus.Bootstrap.keydownFix = true;
}
}
});
// init ondomready
$($.SmartMenus.Bootstrap.init);
return $;
}));