|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
- * jdMenu 1.3.beta2 (2007-03-06)
|
|
|
|
|
|
+ * jdMenu 1.4.1 (2008-03-31)
|
|
*
|
|
*
|
|
* Copyright (c) 2006,2007 Jonathan Sharp (http://jdsharp.us)
|
|
* Copyright (c) 2006,2007 Jonathan Sharp (http://jdsharp.us)
|
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
|
@@ -7,429 +7,165 @@
|
|
*
|
|
*
|
|
* http://jdsharp.us/
|
|
* http://jdsharp.us/
|
|
*
|
|
*
|
|
- * Built upon jQuery 1.1.1 (http://jquery.com)
|
|
|
|
- * This also requires the jQuery dimensions plugin
|
|
|
|
|
|
+ * Built upon jQuery 1.2.1 (http://jquery.com)
|
|
|
|
+ * This also requires the jQuery dimensions >= 1.2 plugin
|
|
*/
|
|
*/
|
|
-(function($){
|
|
|
|
- // This will store an element list of all our menu objects
|
|
|
|
- var jdMenu = [];
|
|
|
|
-
|
|
|
|
- // Public methods
|
|
|
|
- $.fn.jdMenu = function(inSettings) {
|
|
|
|
- var settings = $.extend({}, arguments.callee.defaults, inSettings);
|
|
|
|
- return this.each(function() {
|
|
|
|
- jdMenu.push(this);
|
|
|
|
- $(this).addClass('jd_menu_flag_root');
|
|
|
|
- this.$settings = $.extend({}, settings, {isVerticalMenu: $(this).is('.jd_menu_vertical')});
|
|
|
|
- addEvents(this);
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- $.fn.jdMenuShow = function() {
|
|
|
|
- return this.each(function() {
|
|
|
|
- showMenuLI.apply(this);
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- $.fn.jdMenuHide = function() {
|
|
|
|
- return this.each(function() {
|
|
|
|
- hideMenuUL.apply(this);
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
|
|
|
|
- // Private methods and logic
|
|
|
|
- $(window)
|
|
|
|
- // Bind a click event to hide all visible menus when the document is clicked
|
|
|
|
- .bind('click', function(){
|
|
|
|
- $(jdMenu).find('ul:visible').jdMenuHide();
|
|
|
|
- })
|
|
|
|
- // Cleanup after ourself by nulling the $settings object
|
|
|
|
- .bind('unload', function() {
|
|
|
|
- $(jdMenu).each(function() {
|
|
|
|
- this.$settings = null;
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
|
|
+// This initializes the menu
|
|
|
|
+$(function() {
|
|
|
|
+ $('ul.jd_menu').jdMenu();
|
|
|
|
+});
|
|
|
|
|
|
- // These are our default settings for this plugin
|
|
|
|
- $.fn.jdMenu.defaults = {
|
|
|
|
- activateDelay: 750,
|
|
|
|
- showDelay: 150,
|
|
|
|
- hideDelay: 550,
|
|
|
|
- onShow: null,
|
|
|
|
- onHideCheck: null,
|
|
|
|
- onHide: null,
|
|
|
|
- onAnimate: null,
|
|
|
|
- onClick: null,
|
|
|
|
- offsetX: 4,
|
|
|
|
- offsetY: 2,
|
|
|
|
- iframe: $.browser.msie
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // Our special parentsUntil method to get all parents up to and including the matched element
|
|
|
|
- $.fn.parentsUntil = function(match) {
|
|
|
|
- var a = [];
|
|
|
|
- $(this[0]).parents().each(function() {
|
|
|
|
- a.push(this);
|
|
|
|
- return !$(this).is(match);
|
|
|
|
- });
|
|
|
|
- return this.pushStack(a, arguments);
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // Returns our settings object for this menu
|
|
|
|
- function getSettings(el) {
|
|
|
|
- return $(el).parents('ul.jd_menu_flag_root')[0].$settings;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Unbind any events and then rebind them
|
|
|
|
|
|
+(function($){
|
|
function addEvents(ul) {
|
|
function addEvents(ul) {
|
|
- removeEvents(ul);
|
|
|
|
|
|
+ var settings = $.data( $(ul).parents().andSelf().filter('ul.jd_menu')[0], 'jdMenuSettings' );
|
|
$('> li', ul)
|
|
$('> li', ul)
|
|
- .hover(hoverOverLI, hoverOutLI)
|
|
|
|
- .bind('click', itemClick)
|
|
|
|
- .find('> a.accessible')
|
|
|
|
- .bind('click', accessibleClick);
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // Remove all events for this menu
|
|
|
|
- function removeEvents(ul) {
|
|
|
|
- $('> li', ul)
|
|
|
|
- .unbind('mouseover').unbind('mouseout')
|
|
|
|
- .unbind('click')
|
|
|
|
- .find('> a.accessible')
|
|
|
|
- .unbind('click');
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- function hoverOverLI() {
|
|
|
|
- var cls = 'jd_menu_hover' + ($(this).parent().is('.jd_menu_flag_root') ? '_menubar' : '');
|
|
|
|
- $(this).addClass(cls).find('> a').addClass(cls);
|
|
|
|
-
|
|
|
|
- if (this.$timer) {
|
|
|
|
- clearTimeout(this.$timer);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Do we have a sub menu?
|
|
|
|
- if ($('> ul', this).size() > 0) {
|
|
|
|
- var settings = getSettings(this);
|
|
|
|
-
|
|
|
|
- // Which delay to use, the longer activate one or the shorter show delay if a menu is already visible
|
|
|
|
- var delay = ($(this).parents('ul.jd_menu_flag_root').find('ul:visible').size() == 0)
|
|
|
|
- ? settings.activateDelay : settings.showDelay;
|
|
|
|
- var t = this;
|
|
|
|
- this.$timer = setTimeout(function() {
|
|
|
|
- showMenuLI.apply(t);
|
|
|
|
- }, delay);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- function hoverOutLI() {
|
|
|
|
- // Remove both classes so we do not have to test which one we are
|
|
|
|
- $(this) .removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar')
|
|
|
|
|
|
+ .bind('mouseenter.jdmenu mouseleave.jdmenu', function(evt) {
|
|
|
|
+ $(this).toggleClass('jdm_hover');
|
|
|
|
+ var ul = $('> ul', this);
|
|
|
|
+ if ( ul.length == 1 ) {
|
|
|
|
+ clearTimeout( this.$jdTimer );
|
|
|
|
+ var enter = ( evt.type == 'mouseenter' );
|
|
|
|
+ var fn = ( enter ? showMenu : hideMenu );
|
|
|
|
+ this.$jdTimer = setTimeout(function() {
|
|
|
|
+ fn( ul[0], settings.onAnimate, settings.isVertical );
|
|
|
|
+ }, enter ? settings.showDelay : settings.hideDelay );
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .bind('click.jdmenu', function(evt) {
|
|
|
|
+ var ul = $('> ul', this);
|
|
|
|
+ if ( ul.length == 1 &&
|
|
|
|
+ ( settings.disableLinks == true || $(this).hasClass('accessible') ) ) {
|
|
|
|
+ showMenu( ul, settings.onAnimate, settings.isVertical );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // The user clicked the li and we need to trigger a click for the a
|
|
|
|
+ if ( evt.target == this ) {
|
|
|
|
+ var link = $('> a', evt.target).not('.accessible');
|
|
|
|
+ if ( link.length > 0 ) {
|
|
|
|
+ var a = link[0];
|
|
|
|
+ if ( !a.onclick ) {
|
|
|
|
+ window.open( a.href, a.target || '_self' );
|
|
|
|
+ } else {
|
|
|
|
+ $(a).trigger('click');
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if ( settings.disableLinks ||
|
|
|
|
+ ( !settings.disableLinks && !$(this).parent().hasClass('jd_menu') ) ) {
|
|
|
|
+ $(this).parent().jdMenuHide();
|
|
|
|
+ evt.stopPropagation();
|
|
|
|
+ }
|
|
|
|
+ })
|
|
.find('> a')
|
|
.find('> a')
|
|
- .removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar');
|
|
|
|
-
|
|
|
|
- if (this.$timer) {
|
|
|
|
- clearTimeout(this.$timer);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // TODO: Possible bug with our test for visibility in that parent menus are hidden child menus are not
|
|
|
|
|
|
+ .bind('focus.jdmenu blur.jdmenu', function(evt) {
|
|
|
|
+ var p = $(this).parents('li:eq(0)');
|
|
|
|
+ if ( evt.type == 'focus' ) {
|
|
|
|
+ p.addClass('jdm_hover');
|
|
|
|
+ } else {
|
|
|
|
+ p.removeClass('jdm_hover');
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .filter('.accessible')
|
|
|
|
+ .bind('click.jdmenu', function(evt) {
|
|
|
|
+ evt.preventDefault();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
|
|
- // If we have a visible menu, hide it
|
|
|
|
- if ($(this).is(':visible') && $('> ul', this).size() > 0) {
|
|
|
|
- var settings = getSettings(this);
|
|
|
|
- var ul = $('> ul', this)[0];
|
|
|
|
- this.$timer = setTimeout(function() {
|
|
|
|
- hideMenuUL.apply(ul);
|
|
|
|
- }, settings.hideDelay);
|
|
|
|
|
|
+ function showMenu(ul, animate, vertical) {
|
|
|
|
+ var ul = $(ul);
|
|
|
|
+ if ( ul.is(':visible') ) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ ul.bgiframe();
|
|
|
|
+ var li = ul.parent();
|
|
|
|
+ ul .trigger('jdMenuShow')
|
|
|
|
+ .positionBy({ target: li[0],
|
|
|
|
+ targetPos: ( vertical === true || !li.parent().hasClass('jd_menu') ? 1 : 3 ),
|
|
|
|
+ elementPos: 0,
|
|
|
|
+ hideAfterPosition: true
|
|
|
|
+ });
|
|
|
|
+ if ( !ul.hasClass('jdm_events') ) {
|
|
|
|
+ ul.addClass('jdm_events');
|
|
|
|
+ addEvents(ul);
|
|
|
|
+ }
|
|
|
|
+ li .addClass('jdm_active')
|
|
|
|
+ // Hide any adjacent menus
|
|
|
|
+ .siblings('li').find('> ul:eq(0):visible')
|
|
|
|
+ .each(function(){
|
|
|
|
+ hideMenu( this );
|
|
|
|
+ });
|
|
|
|
+ if ( animate === undefined ) {
|
|
|
|
+ ul.show();
|
|
|
|
+ } else {
|
|
|
|
+ animate.apply( ul[0], [true] );
|
|
}
|
|
}
|
|
- };
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- // "this" is a reference to the LI element that contains
|
|
|
|
- // the UL that will be shown
|
|
|
|
- function showMenuLI() {
|
|
|
|
- var ul = $('> ul', this).get(0);
|
|
|
|
- // We are already visible, just return
|
|
|
|
- if ($(ul).is(':visible')) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Clear our timer if it exists
|
|
|
|
- if (this.$timer) {
|
|
|
|
- clearTimeout(this.$timer);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Get our settings object
|
|
|
|
- var settings = getSettings(this);
|
|
|
|
-
|
|
|
|
- // Call our callback
|
|
|
|
- if (settings.onShow != null && settings.onShow.apply(this) == false) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Add hover classes, needed for accessible functionality
|
|
|
|
- var isRoot = $(this).parent().is('.jd_menu_flag_root');
|
|
|
|
- var c = 'jd_menu_active' + (isRoot ? '_menubar' : '');
|
|
|
|
- $(this).addClass(c).find('> a').addClass(c);
|
|
|
|
-
|
|
|
|
- if (!isRoot) {
|
|
|
|
- // Add the active class to the parent list item which maybe our menubar
|
|
|
|
- var c = 'jd_menu_active' + ($(this).parent().parent().parent().is('.jd_menu_flag_root') ? '_menubar' : '');
|
|
|
|
- $(this).parent().parent().addClass(c).find('> a').addClass(c);
|
|
|
|
|
|
+ function hideMenu(ul, animate) {
|
|
|
|
+ var ul = $(ul);
|
|
|
|
+ $('.bgiframe', ul).remove();
|
|
|
|
+ ul .filter(':not(.jd_menu)')
|
|
|
|
+ .find('> li > ul:eq(0):visible')
|
|
|
|
+ .each(function() {
|
|
|
|
+ hideMenu( this );
|
|
|
|
+ })
|
|
|
|
+ .end();
|
|
|
|
+ if ( animate === undefined ) {
|
|
|
|
+ ul.hide()
|
|
|
|
+ } else {
|
|
|
|
+ animate.apply( ul[0], [false] );
|
|
}
|
|
}
|
|
|
|
|
|
- // Hide any existing menues at the same level
|
|
|
|
- $(this).parent().find('> li > ul:visible').not(ul).each(function() {
|
|
|
|
- hideMenuUL.apply(this);
|
|
|
|
|
|
+ ul .trigger('jdMenuHide')
|
|
|
|
+ .parents('li:eq(0)')
|
|
|
|
+ .removeClass('jdm_active jdm_hover')
|
|
|
|
+ .end()
|
|
|
|
+ .find('> li')
|
|
|
|
+ .removeClass('jdm_active jdm_hover');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Public methods
|
|
|
|
+ $.fn.jdMenu = function(settings) {
|
|
|
|
+ // Future settings: activateDelay
|
|
|
|
+ var settings = $.extend({ // Time in ms before menu shows
|
|
|
|
+ showDelay: 200,
|
|
|
|
+ // Time in ms before menu hides
|
|
|
|
+ hideDelay: 500,
|
|
|
|
+ // Should items that contain submenus not
|
|
|
|
+ // respond to clicks
|
|
|
|
+ disableLinks: true
|
|
|
|
+ // This callback allows for you to animate menus
|
|
|
|
+ //onAnimate: null
|
|
|
|
+ }, settings);
|
|
|
|
+ if ( !$.isFunction( settings.onAnimate ) ) {
|
|
|
|
+ settings.onAnimate = undefined;
|
|
|
|
+ }
|
|
|
|
+ return this.filter('ul.jd_menu').each(function() {
|
|
|
|
+ $.data( this,
|
|
|
|
+ 'jdMenuSettings',
|
|
|
|
+ $.extend({ isVertical: $(this).hasClass('jd_menu_vertical') }, settings)
|
|
|
|
+ );
|
|
|
|
+ addEvents(this);
|
|
});
|
|
});
|
|
-
|
|
|
|
- addEvents(ul);
|
|
|
|
-
|
|
|
|
- // Our range object is used in calculating menu positions
|
|
|
|
- var Range = function(x1, x2, y1, y2) {
|
|
|
|
- this.x1 = x1;
|
|
|
|
- this.x2 = x2;
|
|
|
|
- this.y1 = y1;
|
|
|
|
- this.y2 = y2;
|
|
|
|
- }
|
|
|
|
- Range.prototype.contains = function(range) {
|
|
|
|
- return (this.x1 <= range.x1 && range.x2 <= this.x2)
|
|
|
|
- &&
|
|
|
|
- (this.y1 <= range.y1 && range.y2 <= this.y2);
|
|
|
|
- }
|
|
|
|
- Range.prototype.transform = function(x, y) {
|
|
|
|
- return new Range(this.x1 + x, this.x2 + x, this.y1 + y, this.y2 + y);
|
|
|
|
- }
|
|
|
|
- Range.prototype.nudgeX = function(range) {
|
|
|
|
- if (this.x1 < range.x1) {
|
|
|
|
- return new Range(range.x1, range.x1 + (this.x2 - this.x1), this.y1, this.y2);
|
|
|
|
- } else if (this.x2 > range.x2) {
|
|
|
|
- return new Range(range.x2 - (this.x2 - this.x1), range.x2, this.y1, this.y2);
|
|
|
|
- }
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
- Range.prototype.nudgeY = function(range) {
|
|
|
|
- if (this.y1 < range.y1) {
|
|
|
|
- return new Range(this.x1, this.x2, range.y1, range.y1 + (this.y2 - this.y1));
|
|
|
|
- } else if (this.y2 > range.y2) {
|
|
|
|
- return new Range(this.x1, this.x2, range.y2 - (this.y2 - this.y1), range.y2);
|
|
|
|
- }
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // window width & scroll offset
|
|
|
|
- var sx = $(window).scrollLeft()
|
|
|
|
- var sy = $(window).scrollTop();
|
|
|
|
- var ww = $(window).innerWidth();
|
|
|
|
- var wh = $(window).innerHeight();
|
|
|
|
-
|
|
|
|
- var viewport = new Range( sx, sx + ww,
|
|
|
|
- sy, sy + wh);
|
|
|
|
-
|
|
|
|
- // "Show" our menu so we can calculate its width, set left and top so that it does not accidentally
|
|
|
|
- // go offscreen and trigger browser scroll bars
|
|
|
|
- $(ul).css({visibility: 'hidden', left: 0, top: 0}).show();
|
|
|
|
-
|
|
|
|
- var menuWidth = $(ul).outerWidth();
|
|
|
|
- var menuHeight = $(ul).outerHeight();
|
|
|
|
-
|
|
|
|
- // Get the LI parent UL outerwidth in case borders are applied to it
|
|
|
|
- var tp = $(this).parent();
|
|
|
|
- var thisWidth = tp.outerWidth();
|
|
|
|
- var thisBorderWidth = parseInt(tp.css('borderLeftWidth')) + parseInt(tp.css('borderRightWidth'));
|
|
|
|
- //var thisBorderTop = parseInt(tp.css('borderTopWidth'));
|
|
|
|
- var thisHeight = $(this).outerHeight();
|
|
|
|
- var thisOffset = $(this).offset({border: false});
|
|
|
|
-
|
|
|
|
- $(ul).hide().css({visibility: ''});
|
|
|
|
-
|
|
|
|
- // We define a list of valid positions for our menu and then test against them to find one that works best
|
|
|
|
- var position = [];
|
|
|
|
- // Bottom Horizontal
|
|
|
|
- // Menu is directly below and left edges aligned to parent item
|
|
|
|
- position[0] = new Range(thisOffset.left, thisOffset.left + menuWidth,
|
|
|
|
- thisOffset.top + thisHeight, thisOffset.top + thisHeight + menuHeight);
|
|
|
|
- // Menu is directly below and right edges aligned to parent item
|
|
|
|
- position[1] = new Range((thisOffset.left + thisWidth) - menuWidth, thisOffset.left + thisWidth,
|
|
|
|
- position[0].y1, position[0].y2);
|
|
|
|
- // Menu is "nudged" horizontally below parent item
|
|
|
|
- position[2] = position[0].nudgeX(viewport);
|
|
|
|
-
|
|
|
|
- // Right vertical
|
|
|
|
- // Menu is directly right and top edge aligned to parent item
|
|
|
|
- position[3] = new Range(thisOffset.left + thisWidth - thisBorderWidth, thisOffset.left + thisWidth - thisBorderWidth + menuWidth,
|
|
|
|
- thisOffset.top, thisOffset.top + menuHeight);
|
|
|
|
- // Menu is directly right and bottom edges aligned with parent item
|
|
|
|
- position[4] = new Range(position[3].x1, position[3].x2,
|
|
|
|
- position[0].y1 - menuHeight, position[0].y1);
|
|
|
|
- // Menu is "nudged" vertically to right of parent item
|
|
|
|
- position[5] = position[3].nudgeY(viewport);
|
|
|
|
-
|
|
|
|
- // Top Horizontal
|
|
|
|
- // Menu is directly top and left edges aligned to parent item
|
|
|
|
- position[6] = new Range(thisOffset.left, thisOffset.left + menuWidth,
|
|
|
|
- thisOffset.top - menuHeight, thisOffset.top);
|
|
|
|
- // Menu is directly top and right edges aligned to parent item
|
|
|
|
- position[7] = new Range((thisOffset.left + thisWidth) - menuWidth, thisOffset.left + thisWidth,
|
|
|
|
- position[6].y1, position[6].y2);
|
|
|
|
- // Menu is "nudged" horizontally to the top of parent item
|
|
|
|
- position[8] = position[6].nudgeX(viewport);
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- // Left vertical
|
|
|
|
- // Menu is directly left and top edges aligned to parent item
|
|
|
|
- position[9] = new Range(thisOffset.left - menuWidth, thisOffset.left,
|
|
|
|
- position[3].y1, position[3].y2);
|
|
|
|
- // Menu is directly left and bottom edges aligned to parent item
|
|
|
|
- position[10]= new Range(position[9].x1, position[9].x2,
|
|
|
|
- position[4].y1 + thisHeight - menuHeight, position[4].y1 + thisHeight);
|
|
|
|
- // Menu is "nudged" vertically to left of parent item
|
|
|
|
- position[11]= position[10].nudgeY(viewport);
|
|
|
|
-
|
|
|
|
- // This defines the order in which we test our positions
|
|
|
|
- var order = [];
|
|
|
|
- if ($(this).parent().is('.jd_menu_flag_root') && !settings.isVerticalMenu) {
|
|
|
|
- order = [0, 1, 2, 6, 7, 8, 5, 11];
|
|
|
|
- } else {
|
|
|
|
- order = [3, 4, 5, 9, 10, 11, 0, 1, 2, 6, 7, 8];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Set our default position (first position) if no others can be found
|
|
|
|
- var pos = order[0];
|
|
|
|
- for (var i = 0, j = order.length; i < j; i++) {
|
|
|
|
- // If this position for our menu is within the viewport of the browser, use this position
|
|
|
|
- if (viewport.contains(position[order[i]])) {
|
|
|
|
- pos = order[i];
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- var menuPosition = position[pos];
|
|
|
|
-
|
|
|
|
- // Find if we are absolutely positioned or have an absolutely positioned parent
|
|
|
|
- $(this).add($(this).parents()).each(function() {
|
|
|
|
- if ($(this).css('position') == 'absolute') {
|
|
|
|
- var abs = $(this).offset();
|
|
|
|
- // Transform our coordinates to be relative to the absolute parent
|
|
|
|
- menuPosition = menuPosition.transform(-abs.left, -abs.top);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ $.fn.jdMenuUnbind = function() {
|
|
|
|
+ $('ul.jdm_events', this)
|
|
|
|
+ .unbind('.jdmenu')
|
|
|
|
+ .find('> a').unbind('.jdmenu');
|
|
|
|
+ };
|
|
|
|
+ $.fn.jdMenuHide = function() {
|
|
|
|
+ return this.filter('ul').each(function(){
|
|
|
|
+ hideMenu( this );
|
|
});
|
|
});
|
|
|
|
+ };
|
|
|
|
|
|
- switch (pos) {
|
|
|
|
- case 3:
|
|
|
|
- menuPosition.y1 += settings.offsetY;
|
|
|
|
- case 4:
|
|
|
|
- menuPosition.x1 -= settings.offsetX;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case 9:
|
|
|
|
- menuPosition.y1 += settings.offsetY;
|
|
|
|
- case 10:
|
|
|
|
- menuPosition.x1 += settings.offsetX;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (settings.iframe) {
|
|
|
|
- $(ul).bgiframe();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (settings.onAnimate) {
|
|
|
|
- $(ul).css({left: menuPosition.x1, top: menuPosition.y1});
|
|
|
|
- // The onAnimate method is expected to "show" the element it is passed
|
|
|
|
- settings.onAnimate.apply(ul, [true]);
|
|
|
|
- } else {
|
|
|
|
- $(ul).css({left: menuPosition.x1, top: menuPosition.y1}).show();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // "this" is a reference to a UL menu to be hidden
|
|
|
|
- function hideMenuUL(recurse) {
|
|
|
|
- if (!$(this).is(':visible')) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var settings = getSettings(this);
|
|
|
|
-
|
|
|
|
- // Test if this menu should get hidden
|
|
|
|
- if (settings.onHideCheck != null && settings.onHideCheck.apply(this) == false) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Hide all of our child menus first
|
|
|
|
- $('> li ul:visible', this).each(function() {
|
|
|
|
- hideMenuUL.apply(this, [false]);
|
|
|
|
|
|
+ // Private methods and logic
|
|
|
|
+ $(window)
|
|
|
|
+ // Bind a click event to hide all visible menus when the document is clicked
|
|
|
|
+ .bind('click.jdmenu', function(){
|
|
|
|
+ $('ul.jd_menu ul:visible').jdMenuHide();
|
|
});
|
|
});
|
|
-
|
|
|
|
- // If we are the root, do not hide ourself
|
|
|
|
- if ($(this).is('.jd_menu_flag_root')) {
|
|
|
|
- alert('We are root');
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var elms = $('> li', this).add($(this).parent());
|
|
|
|
- elms.removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar')
|
|
|
|
- .removeClass('jd_menu_active').removeClass('jd_menu_active_menubar')
|
|
|
|
- .find('> a')
|
|
|
|
- .removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar')
|
|
|
|
- .removeClass('jd_menu_active').removeClass('jd_menu_active_menubar');
|
|
|
|
-
|
|
|
|
- removeEvents(this);
|
|
|
|
- $(this).each(function() {
|
|
|
|
- if (settings.onAnimate != null) {
|
|
|
|
- settings.onAnimate.apply(this, [false]);
|
|
|
|
- } else {
|
|
|
|
- $(this).hide();
|
|
|
|
- }
|
|
|
|
- }).find('> .bgiframe').remove();
|
|
|
|
- // Our callback for after our menu is hidden
|
|
|
|
- if (settings.onHide != null) {
|
|
|
|
- settings.onHide.apply(this);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Recursively hide our parent menus
|
|
|
|
- if (recurse == true) {
|
|
|
|
- $(this).parentsUntil('ul.jd_menu_flag_root')
|
|
|
|
- .removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar')
|
|
|
|
- .not('.jd_menu_flag_root').filter('ul')
|
|
|
|
- .each(function() {
|
|
|
|
- hideMenuUL.apply(this, [false]);
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Prevent the default (usually following a link)
|
|
|
|
- function accessibleClick(e) {
|
|
|
|
- if ($(this).is('.accessible')) {
|
|
|
|
- // Stop the browser from the default link action allowing the
|
|
|
|
- // click event to propagate to propagate to our LI (itemClick function)
|
|
|
|
- e.preventDefault();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Trigger a menu click
|
|
|
|
- function itemClick(e) {
|
|
|
|
- e.stopPropagation();
|
|
|
|
-
|
|
|
|
- var settings = getSettings(this);
|
|
|
|
- if (settings.onClick != null && settings.onClick.apply(this) == false) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ($('> ul', this).size() > 0) {
|
|
|
|
- showMenuLI.apply(this);
|
|
|
|
- } else {
|
|
|
|
- if (e.target == this) {
|
|
|
|
- var link = $('> a', e.target).not('.accessible');
|
|
|
|
- if (link.size() > 0) {
|
|
|
|
- var a = link.get(0);
|
|
|
|
- if (!a.onclick) {
|
|
|
|
- window.open(a.href, a.target || '_self');
|
|
|
|
- } else {
|
|
|
|
- $(a).click();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- hideMenuUL.apply($(this).parent(), [true]);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
})(jQuery);
|
|
})(jQuery);
|