1// jQuery.dropdown_menu() by Daniel Upshaw 2012-2013 2// http://danielupshaw.com/jquery-css-dropdown-plugin/readme.html 3 4// Beginning semi-colon for concatenated scripts and any improperly closed plugins 5;(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 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 + '">»</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())
112- 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 );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.