Skip to content

Commit b0c750f

Browse files
committed
Update dropdown-menu.js
Fix for latest 1.x jQuery
1 parent 9bcabc3 commit b0c750f

File tree

1 file changed

+179
-178
lines changed

1 file changed

+179
-178
lines changed

dropdown-menu.js

Lines changed: 179 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,182 +1,183 @@
1-
// jQuery().dropdown_menu() by Daniel Upshaw 2012-2013
1+
// jQuery.dropdown_menu() by Daniel Upshaw 2012-2013
22
// http://danielupshaw.com/jquery-css-dropdown-plugin/readme.html
33

44
// Beginning semi-colon for concatenated scripts and any improperly closed plugins
55
;(function( $, window, document, undefined ) {
6-
$.fn.extend({
7-
dropdown_menu : function (options) {
8-
var _defaults = {
9-
sub_indicator_class : 'dropdown-menu-sub-indicator', // Class given to LI's with submenus
10-
vertical_class : 'dropdown-menu-vertical', // Class for a vertical menu
11-
shadow_class : 'dropdown-menu-shadow', // Class for drop shadow on submenus
12-
hover_class : 'dropdown-menu-hover', // Class applied to hovered LI's
13-
open_delay : 150, // Delay on menu open
14-
close_delay : 300, // Delay on menu close
15-
animation_open : { opacity : 'show' }, // Animation for menu open
16-
speed_open : 'fast', // Animation speed for menu open
17-
animation_close : { opacity : 'hide' }, // Animation for menu close
18-
speed_close : 'fast', // Animation speed for menu close
19-
sub_indicators : false, // Whether to show arrows for submenus
20-
drop_shadows : false, // Whether to apply drop shadow class to submenus
21-
vertical : false, // Whether the root menu is vertically aligned
22-
viewport_overflow : 'auto', // Handle submenu opening offscreen: "auto", "move", "scroll", or false
23-
init : function() {} // Callback function applied on init
24-
};
25-
26-
// Test for IE <= 7
27-
var ie7 = ($.browser.msie && $.browser.version < 8);
28-
29-
return this.each(function() {
30-
var menu = $(this);
31-
// Needs this single/double quote precedence for JSON data
32-
// <ul data-options='{"sub_indicators":"true"}'></ul>
33-
var metadata = menu.data('options');
34-
var o = $.extend({}, _defaults, options, metadata);
35-
36-
// Arrow element
37-
var sub_indicator = $('<span class="' + o.sub_indicator_class + '">&#187;</span>');
38-
39-
// Add vertical menu class
40-
if (o.vertical) {
41-
menu.addClass(o.vertical_class);
42-
}
43-
44-
// Remove whitespace between inline-block elements
45-
$('>li', menu).css({ 'font-size' : menu.css('font-size') });
46-
menu.css({ 'font-size' : '0' });
47-
48-
menu.find('li:has(ul)').each(function() {
49-
// Add a class to the LI to indicate that it has a submenu
50-
$(this).addClass(o.sub_indicator_class);
51-
52-
// Add arrow/indicator element if enabled
53-
if (o.sub_indicators) {
54-
$('>a:first-child', this).append(sub_indicator.clone());
55-
}
56-
57-
// Get the submenu and hide it, but keep display:block so the width can be calculated
58-
var submenu = $('>ul', this).css({ 'visibility' : 'hidden', 'display' : 'block' });
59-
60-
// Add drop shadow class if enabled
61-
if (o.drop_shadows) {
62-
submenu.addClass(o.shadow_class);
63-
}
64-
65-
// IE <= 7
66-
if (ie7) {
67-
// Wrap in setTimeout() else the arrow may not be included
68-
setTimeout(function() {
69-
// Lock submenu UL width in CSS so that the LI's can stretch
70-
submenu.css({ 'width' : submenu.width() });
71-
}, 0);
72-
}
73-
74-
// Handle hover states
75-
$(this).on({
76-
mouseenter : function(e) {
77-
clearTimeout($(this).data('close_timer'));
78-
clearTimeout($(this).data('open_timer'));
79-
80-
// If the submenu has already been opened
81-
if ($(this).hasClass(o.hover_class)) {
82-
return;
83-
}
84-
85-
// $.proxy() keeps "this" context
86-
$(this).data('open_timer', setTimeout($.proxy(function() {
87-
$(this).addClass(o.hover_class);
88-
89-
// For vertical menus
90-
if (o.vertical) {
91-
submenu.css({ 'top' : 0 , 'left' : $(this).width() });
92-
} else {
93-
submenu.css({ 'top' : '', 'left' : '' });
94-
}
95-
96-
// So we can check the offset
97-
submenu.css({ 'visibility' : 'hidden', 'display' : 'block' });
98-
99-
// Check if the submenu is overflowing off the page
100-
overflow_x = submenu.offset().left + submenu.width() > $(window).scrollLeft() + $(window).width();
101-
overflow_y = submenu.offset().top + submenu.height() > $(window).scrollTop() + $(window).height();
102-
overflow = overflow_x || overflow_y;
103-
104-
if (overflow && o.viewport_overflow) {
105-
// Padding to accomodate for drop shgadows, etc
106-
var padding = 10;
107-
if (o.viewport_overflow === 'auto') o.viewport_overflow = ie7 ? 'scroll' : 'move';
108-
109-
switch (o.viewport_overflow) {
110-
case 'move' :
111-
var left = overflow_x ? ($(window).scrollLeft() + $(window).width()) - submenu.width() - padding : submenu.offset().left;
112-
var top = overflow_y ? ($(window).scrollTop() + $(window).height()) - submenu.height() - padding : submenu.offset().top;
113-
submenu.offset({ left : left , top : top });
114-
break;
115-
case 'scroll' :
116-
if (overflow_x) {
117-
var scrollLeft = submenu.offset().left - $(window).width() + submenu.width() + padding;
118-
$('html').animate({ scrollLeft : scrollLeft }, 'fast');
119-
//$(window).scrollLeft(scrollLeft);
120-
}
121-
if (overflow_y) {
122-
var scrollTop = submenu.offset().top - $(window).height() + submenu.height() + padding;
123-
$('html').animate({ scrollTop : scrollTop }, 'fast');
124-
//$(window).scrollTop(scrollTop);
125-
}
126-
break;
127-
}
128-
}
129-
130-
// Restore display state
131-
submenu.hide().css({ 'visibility' : 'visible' });
132-
133-
if (o.animation_open) {
134-
submenu.animate(o.animation_open, o.speed_open);
135-
} else {
136-
submenu.show();
137-
}
138-
}, this), o.open_delay));
139-
},
140-
mouseleave : function(e) {
141-
clearTimeout($(this).data('close_timer'));
142-
clearTimeout($(this).data('open_timer'));
143-
144-
$(this).data('close_timer', setTimeout($.proxy(function() {
145-
$(this).removeClass(o.hover_class);
146-
147-
if (o.animation_close) {
148-
submenu.animate(o.animation_close, o.speed_close, function() {
149-
submenu.css({ 'visibility' : 'hidden' });
150-
});
151-
} else {
152-
submenu.hide().css({ 'visibility' : 'hidden' });
153-
}
154-
}, this), o.close_delay));
155-
},
156-
// For touch devices, disable the link if its submenu is not showing yet
157-
touchstart : function(e) {
158-
$('>a:first-child', this).one('click', $.proxy(function(e) {
159-
if (!$(this).hasClass(o.hover_class)) {
160-
e.preventDefault();
161-
} else {
162-
return true;
163-
}
164-
}, this));
165-
}
166-
});
167-
});
168-
169-
// Wrap in setTimeout() to ensure processes have completed
170-
setTimeout(function() {
171-
// Completely hide the submenus
172-
$('ul', menu).hide(1)
173-
.promise()
174-
.done(function() {
175-
// Apply the init callback
176-
o.init.call(menu[0]);
177-
});
178-
}, 0);
179-
});
180-
}
181-
});
182-
})( jQuery, window , document );
6+
$.fn.extend({
7+
dropdown_menu : function (options) {
8+
var _defaults = {
9+
sub_indicator_class : 'dropdown-menu-sub-indicator', // Class given to LI's with submenus
10+
vertical_class : 'dropdown-menu-vertical', // Class for a vertical menu
11+
shadow_class : 'dropdown-menu-shadow', // Class for drop shadow on submenus
12+
hover_class : 'dropdown-menu-hover', // Class applied to hovered LI's
13+
open_delay : 150, // Delay on menu open
14+
close_delay : 300, // Delay on menu close
15+
animation_open : { opacity : 'show' }, // Animation for menu open
16+
speed_open : 'fast', // Animation speed for menu open
17+
animation_close : { opacity : 'hide' }, // Animation for menu close
18+
speed_close : 'fast', // Animation speed for menu close
19+
sub_indicators : false, // Whether to show arrows for submenus
20+
drop_shadows : false, // Whether to apply drop shadow class to submenus
21+
vertical : false, // Whether the root menu is vertically aligned
22+
viewport_overflow : 'auto', // Handle submenu opening offscreen: "auto", "move", "scroll", or false
23+
init : function() {} // Callback function applied on init
24+
};
25+
26+
// Test for IE <= 7
27+
version = parseFloat(navigator.appVersion.split("MSIE")[1]);
28+
var ie7 = (version < 8) && (document.body.filters);
29+
30+
return this.each(function() {
31+
var menu = $(this);
32+
// Needs this single/double quote precedence for JSON data
33+
// <ul data-options='{"sub_indicators":"true"}'></ul>
34+
var metadata = menu.data('options');
35+
var o = $.extend({}, _defaults, options, metadata);
36+
37+
// Arrow element
38+
var sub_indicator = $('<span class="' + o.sub_indicator_class + '">&#187;</span>');
39+
40+
// Add vertical menu class
41+
if (o.vertical) {
42+
menu.addClass(o.vertical_class);
43+
}
44+
45+
// Remove whitespace between inline-block elements
46+
$('>li', menu).css({ 'font-size' : menu.css('font-size') });
47+
menu.css({ 'font-size' : '0' });
48+
49+
menu.find('li:has(ul)').each(function() {
50+
// Add a class to the LI to indicate that it has a submenu
51+
$(this).addClass(o.sub_indicator_class);
52+
53+
// Add arrow/indicator element if enabled
54+
if (o.sub_indicators) {
55+
$('>a:first-child', this).append(sub_indicator.clone());
56+
}
57+
58+
// Get the submenu and hide it, but keep display:block so the width can be calculated
59+
var submenu = $('>ul', this).css({ 'visibility' : 'hidden', 'display' : 'block' });
60+
61+
// Add drop shadow class if enabled
62+
if (o.drop_shadows) {
63+
submenu.addClass(o.shadow_class);
64+
}
65+
66+
// IE <= 7
67+
if (ie7) {
68+
// Wrap in setTimeout() else the arrow may not be included
69+
setTimeout(function() {
70+
// Lock submenu UL width in CSS so that the LI's can stretch
71+
submenu.css({ 'width' : submenu.width() });
72+
}, 0);
73+
}
74+
75+
// Handle hover states
76+
$(this).on({
77+
mouseenter : function(e) {
78+
clearTimeout($(this).data('close_timer'));
79+
clearTimeout($(this).data('open_timer'));
80+
81+
// If the submenu has already been opened
82+
if ($(this).hasClass(o.hover_class)) {
83+
return;
84+
}
85+
86+
// $.proxy() keeps "this" context
87+
$(this).data('open_timer', setTimeout($.proxy(function() {
88+
$(this).addClass(o.hover_class);
89+
90+
// For vertical menus
91+
if (o.vertical) {
92+
submenu.css({ 'top' : 0 , 'left' : $(this).width() });
93+
} else {
94+
submenu.css({ 'top' : '', 'left' : '' });
95+
}
96+
97+
// So we can check the offset
98+
submenu.css({ 'visibility' : 'hidden', 'display' : 'block' });
99+
100+
// Check if the submenu is overflowing off the page
101+
overflow_x = submenu.offset().left + submenu.width() > $(window).scrollLeft() + $(window).width();
102+
overflow_y = submenu.offset().top + submenu.height() > $(window).scrollTop() + $(window).height();
103+
overflow = overflow_x || overflow_y;
104+
105+
if (overflow && o.viewport_overflow) {
106+
// Padding to accomodate for drop shadows, etc
107+
var padding = 10;
108+
if (o.viewport_overflow === 'auto') o.viewport_overflow = ie7 ? 'scroll' : 'move';
109+
110+
switch (o.viewport_overflow) {
111+
case 'move' :
112+
var left = overflow_x ? ($(window).scrollLeft() + $(window).width()) - submenu.width() - padding : submenu.offset().left;
113+
var top = overflow_y ? ($(window).scrollTop() + $(window).height()) - submenu.height() - padding : submenu.offset().top;
114+
submenu.offset({ left : left , top : top });
115+
break;
116+
case 'scroll' :
117+
if (overflow_x) {
118+
var scrollLeft = submenu.offset().left - $(window).width() + submenu.width() + padding;
119+
$('html').animate({ scrollLeft : scrollLeft }, 'fast');
120+
//$(window).scrollLeft(scrollLeft);
121+
}
122+
if (overflow_y) {
123+
var scrollTop = submenu.offset().top - $(window).height() + submenu.height() + padding;
124+
$('html').animate({ scrollTop : scrollTop }, 'fast');
125+
//$(window).scrollTop(scrollTop);
126+
}
127+
break;
128+
}
129+
}
130+
131+
// Restore display state
132+
submenu.hide().css({ 'visibility' : 'visible' });
133+
134+
if (o.animation_open) {
135+
submenu.animate(o.animation_open, o.speed_open);
136+
} else {
137+
submenu.show();
138+
}
139+
}, this), o.open_delay));
140+
},
141+
mouseleave : function(e) {
142+
clearTimeout($(this).data('close_timer'));
143+
clearTimeout($(this).data('open_timer'));
144+
145+
$(this).data('close_timer', setTimeout($.proxy(function() {
146+
$(this).removeClass(o.hover_class);
147+
148+
if (o.animation_close) {
149+
submenu.animate(o.animation_close, o.speed_close, function() {
150+
submenu.css({ 'visibility' : 'hidden' });
151+
});
152+
} else {
153+
submenu.hide().css({ 'visibility' : 'hidden' });
154+
}
155+
}, this), o.close_delay));
156+
},
157+
// For touch devices, disable the link if its submenu is not showing yet
158+
touchstart : function(e) {
159+
$('>a:first-child', this).one('click', $.proxy(function(e) {
160+
if (!$(this).hasClass(o.hover_class)) {
161+
e.preventDefault();
162+
} else {
163+
return true;
164+
}
165+
}, this));
166+
}
167+
});
168+
});
169+
170+
// Wrap in setTimeout() to ensure processes have completed
171+
setTimeout(function() {
172+
// Completely hide the submenus
173+
$('ul', menu).hide(1)
174+
.promise()
175+
.done(function() {
176+
// Apply the init callback
177+
o.init.call(menu[0]);
178+
});
179+
}, 0);
180+
});
181+
}
182+
});
183+
})( jQuery, window , document );

0 commit comments

Comments
 (0)