|
1
|
|
|
/* |
|
2
|
|
|
* metismenu - v2.0.3 |
|
3
|
|
|
* A jQuery menu plugin |
|
4
|
|
|
* https://github.com/onokumus/metisMenu |
|
5
|
|
|
* |
|
6
|
|
|
* Made by Osman Nuri Okumus |
|
7
|
|
|
* Under MIT License |
|
8
|
|
|
*/ |
|
9
|
|
|
|
|
10
|
|
|
(function($) { |
|
11
|
|
|
'use strict'; |
|
12
|
|
|
|
|
13
|
|
|
function transitionEnd() { |
|
14
|
|
|
var el = document.createElement('mm'); |
|
15
|
|
|
|
|
16
|
|
|
var transEndEventNames = { |
|
17
|
|
|
WebkitTransition: 'webkitTransitionEnd', |
|
18
|
|
|
MozTransition: 'transitionend', |
|
19
|
|
|
OTransition: 'oTransitionEnd otransitionend', |
|
20
|
|
|
transition: 'transitionend' |
|
21
|
|
|
}; |
|
22
|
|
|
|
|
23
|
|
|
for (var name in transEndEventNames) { |
|
24
|
|
|
if (el.style[name] !== undefined) { |
|
25
|
|
|
return { |
|
26
|
|
|
end: transEndEventNames[name] |
|
27
|
|
|
}; |
|
28
|
|
|
} |
|
29
|
|
|
} |
|
30
|
|
|
return false; |
|
31
|
|
|
} |
|
32
|
|
|
|
|
33
|
|
|
$.fn.emulateTransitionEnd = function(duration) { |
|
34
|
|
|
var called = false; |
|
35
|
|
|
var $el = this; |
|
36
|
|
|
$(this).one('mmTransitionEnd', function() { |
|
37
|
|
|
called = true; |
|
38
|
|
|
}); |
|
39
|
|
|
var callback = function() { |
|
40
|
|
|
if (!called) { |
|
41
|
|
|
$($el).trigger($transition.end); |
|
42
|
|
|
} |
|
43
|
|
|
}; |
|
44
|
|
|
setTimeout(callback, duration); |
|
45
|
|
|
return this; |
|
46
|
|
|
}; |
|
47
|
|
|
|
|
48
|
|
|
var $transition = transitionEnd(); |
|
49
|
|
|
if (!!$transition) { |
|
50
|
|
|
$.event.special.mmTransitionEnd = { |
|
51
|
|
|
bindType: $transition.end, |
|
52
|
|
|
delegateType: $transition.end, |
|
53
|
|
|
handle: function(e) { |
|
54
|
|
|
if ($(e.target).is(this)) { |
|
|
|
|
|
|
55
|
|
|
return e. |
|
56
|
|
|
handleObj. |
|
57
|
|
|
handler. |
|
58
|
|
|
apply(this, arguments); |
|
59
|
|
|
} |
|
60
|
|
|
} |
|
61
|
|
|
}; |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
var MetisMenu = function(element, options) { |
|
65
|
|
|
this.$element = $(element); |
|
66
|
|
|
this.options = $.extend({}, MetisMenu.DEFAULTS, options); |
|
67
|
|
|
this.transitioning = null; |
|
68
|
|
|
|
|
69
|
|
|
this.init(); |
|
70
|
|
|
}; |
|
71
|
|
|
|
|
72
|
|
|
MetisMenu.TRANSITION_DURATION = 350; |
|
73
|
|
|
|
|
74
|
|
|
MetisMenu.DEFAULTS = { |
|
75
|
|
|
toggle: true, |
|
76
|
|
|
doubleTapToGo: false, |
|
77
|
|
|
activeClass: 'active', |
|
78
|
|
|
collapseClass: 'collapse', |
|
79
|
|
|
collapseInClass: 'in', |
|
80
|
|
|
collapsingClass: 'collapsing' |
|
81
|
|
|
}; |
|
82
|
|
|
|
|
83
|
|
|
MetisMenu.prototype.init = function() { |
|
84
|
|
|
var $this = this; |
|
85
|
|
|
var activeClass = this.options.activeClass; |
|
86
|
|
|
var collapseClass = this.options.collapseClass; |
|
87
|
|
|
var collapseInClass = this.options.collapseInClass; |
|
88
|
|
|
|
|
89
|
|
|
this |
|
90
|
|
|
.$element |
|
91
|
|
|
.find('li.' + activeClass) |
|
92
|
|
|
.has('ul') |
|
93
|
|
|
.children('ul') |
|
94
|
|
|
.addClass(collapseClass + ' ' + collapseInClass); |
|
95
|
|
|
|
|
96
|
|
|
this |
|
97
|
|
|
.$element |
|
98
|
|
|
.find('li') |
|
99
|
|
|
.not('.' + activeClass) |
|
100
|
|
|
.has('ul') |
|
101
|
|
|
.children('ul') |
|
102
|
|
|
.addClass(collapseClass); |
|
103
|
|
|
|
|
104
|
|
|
//add the 'doubleTapToGo' class to active items if needed |
|
105
|
|
|
if (this.options.doubleTapToGo) { |
|
106
|
|
|
this |
|
107
|
|
|
.$element |
|
108
|
|
|
.find('li.' + activeClass) |
|
109
|
|
|
.has('ul') |
|
110
|
|
|
.children('a') |
|
111
|
|
|
.addClass('doubleTapToGo'); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
this |
|
115
|
|
|
.$element |
|
116
|
|
|
.find('li') |
|
117
|
|
|
.has('ul') |
|
118
|
|
|
.children('a') |
|
119
|
|
|
.on('click.metisMenu', function(e) { |
|
120
|
|
|
var self = $(this); |
|
121
|
|
|
var $parent = self.parent('li'); |
|
122
|
|
|
var $list = $parent.children('ul'); |
|
123
|
|
|
e.preventDefault(); |
|
124
|
|
|
|
|
125
|
|
|
if ($parent.hasClass(activeClass) && !$this.options.doubleTapToGo) { |
|
126
|
|
|
$this.hide($list); |
|
127
|
|
|
} else { |
|
128
|
|
|
$this.show($list); |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
//Do we need to enable the double tap |
|
132
|
|
|
if ($this.options.doubleTapToGo) { |
|
133
|
|
|
//if we hit a second time on the link and the href is valid, navigate to that url |
|
134
|
|
|
if ($this.doubleTapToGo(self) && self.attr('href') !== '#' && self.attr('href') !== '') { |
|
135
|
|
|
e.stopPropagation(); |
|
136
|
|
|
document.location = self.attr('href'); |
|
137
|
|
|
return; |
|
|
|
|
|
|
138
|
|
|
} |
|
139
|
|
|
} |
|
140
|
|
|
}); |
|
141
|
|
|
}; |
|
142
|
|
|
|
|
143
|
|
|
MetisMenu.prototype.doubleTapToGo = function(elem) { |
|
144
|
|
|
var $this = this.$element; |
|
145
|
|
|
//if the class 'doubleTapToGo' exists, remove it and return |
|
146
|
|
|
if (elem.hasClass('doubleTapToGo')) { |
|
147
|
|
|
elem.removeClass('doubleTapToGo'); |
|
148
|
|
|
return true; |
|
149
|
|
|
} |
|
150
|
|
|
//does not exists, add a new class and return false |
|
151
|
|
|
if (elem.parent().children('ul').length) { |
|
|
|
|
|
|
152
|
|
|
//first remove all other class |
|
153
|
|
|
$this |
|
154
|
|
|
.find('.doubleTapToGo') |
|
155
|
|
|
.removeClass('doubleTapToGo'); |
|
156
|
|
|
//add the class on the current element |
|
157
|
|
|
elem.addClass('doubleTapToGo'); |
|
158
|
|
|
return false; |
|
159
|
|
|
} |
|
160
|
|
|
}; |
|
161
|
|
|
|
|
162
|
|
|
MetisMenu.prototype.show = function(el) { |
|
163
|
|
|
var activeClass = this.options.activeClass; |
|
164
|
|
|
var collapseClass = this.options.collapseClass; |
|
165
|
|
|
var collapseInClass = this.options.collapseInClass; |
|
166
|
|
|
var collapsingClass = this.options.collapsingClass; |
|
167
|
|
|
var $this = $(el); |
|
168
|
|
|
var $parent = $this.parent('li'); |
|
169
|
|
|
if (this.transitioning || $this.hasClass(collapseInClass)) { |
|
170
|
|
|
return; |
|
171
|
|
|
} |
|
172
|
|
|
|
|
173
|
|
|
$parent.addClass(activeClass); |
|
174
|
|
|
|
|
175
|
|
|
if (this.options.toggle) { |
|
176
|
|
|
this.hide($parent.siblings().children('ul.' + collapseInClass)); |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
$this |
|
180
|
|
|
.removeClass(collapseClass) |
|
181
|
|
|
.addClass(collapsingClass) |
|
182
|
|
|
.height(0); |
|
183
|
|
|
|
|
184
|
|
|
this.transitioning = 1; |
|
185
|
|
|
var complete = function() { |
|
186
|
|
|
$this |
|
187
|
|
|
.removeClass(collapsingClass) |
|
188
|
|
|
.addClass(collapseClass + ' ' + collapseInClass) |
|
189
|
|
|
.height(''); |
|
190
|
|
|
this.transitioning = 0; |
|
191
|
|
|
}; |
|
192
|
|
|
if (!$transition) { |
|
193
|
|
|
return complete.call(this); |
|
194
|
|
|
} |
|
195
|
|
|
$this |
|
196
|
|
|
.one('mmTransitionEnd', $.proxy(complete, this)) |
|
197
|
|
|
.emulateTransitionEnd(MetisMenu.TRANSITION_DURATION) |
|
198
|
|
|
.height($this[0].scrollHeight); |
|
199
|
|
|
}; |
|
200
|
|
|
|
|
201
|
|
|
MetisMenu.prototype.hide = function(el) { |
|
202
|
|
|
var activeClass = this.options.activeClass; |
|
203
|
|
|
var collapseClass = this.options.collapseClass; |
|
204
|
|
|
var collapseInClass = this.options.collapseInClass; |
|
205
|
|
|
var collapsingClass = this.options.collapsingClass; |
|
206
|
|
|
var $this = $(el); |
|
207
|
|
|
|
|
208
|
|
|
if (this.transitioning || !$this.hasClass(collapseInClass)) { |
|
209
|
|
|
return; |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
$this.parent('li').removeClass(activeClass); |
|
213
|
|
|
$this.height($this.height())[0].offsetHeight; |
|
|
|
|
|
|
214
|
|
|
|
|
215
|
|
|
$this |
|
216
|
|
|
.addClass(collapsingClass) |
|
217
|
|
|
.removeClass(collapseClass) |
|
218
|
|
|
.removeClass(collapseInClass); |
|
219
|
|
|
|
|
220
|
|
|
this.transitioning = 1; |
|
221
|
|
|
|
|
222
|
|
|
var complete = function() { |
|
223
|
|
|
this.transitioning = 0; |
|
224
|
|
|
$this |
|
225
|
|
|
.removeClass(collapsingClass) |
|
226
|
|
|
.addClass(collapseClass); |
|
227
|
|
|
}; |
|
228
|
|
|
|
|
229
|
|
|
if (!$transition) { |
|
230
|
|
|
return complete.call(this); |
|
231
|
|
|
} |
|
232
|
|
|
$this |
|
233
|
|
|
.height(0) |
|
234
|
|
|
.one('mmTransitionEnd', $.proxy(complete, this)) |
|
235
|
|
|
.emulateTransitionEnd(MetisMenu.TRANSITION_DURATION); |
|
236
|
|
|
}; |
|
237
|
|
|
|
|
238
|
|
|
function Plugin(option) { |
|
239
|
|
|
return this.each(function() { |
|
240
|
|
|
var $this = $(this); |
|
241
|
|
|
var data = $this.data('mm'); |
|
242
|
|
|
var options = $.extend({}, |
|
243
|
|
|
MetisMenu.DEFAULTS, |
|
244
|
|
|
$this.data(), |
|
245
|
|
|
typeof option === 'object' && option |
|
246
|
|
|
); |
|
247
|
|
|
|
|
248
|
|
|
if (!data) { |
|
249
|
|
|
$this.data('mm', (data = new MetisMenu(this, options))); |
|
250
|
|
|
} |
|
251
|
|
|
if (typeof option === 'string') { |
|
252
|
|
|
data[option](); |
|
253
|
|
|
} |
|
254
|
|
|
}); |
|
255
|
|
|
} |
|
256
|
|
|
|
|
257
|
|
|
var old = $.fn.metisMenu; |
|
258
|
|
|
|
|
259
|
|
|
$.fn.metisMenu = Plugin; |
|
260
|
|
|
$.fn.metisMenu.Constructor = MetisMenu; |
|
261
|
|
|
|
|
262
|
|
|
$.fn.metisMenu.noConflict = function() { |
|
263
|
|
|
$.fn.metisMenu = old; |
|
264
|
|
|
return this; |
|
265
|
|
|
}; |
|
266
|
|
|
|
|
267
|
|
|
})(jQuery); |
|
268
|
|
|
|
This check looks for functions where a
returnstatement is found in some execution paths, but not in all.Consider this little piece of code
The function
isBigwill only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly returnundefined.This behaviour may not be what you had intended. In any case, you can add a
return undefinedto the other execution path to make the return value explicit.