(function($){
var jdMenu = [];
$.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);
});
};
$(window)
.bind('click', function(){
$(jdMenu).find('ul:visible').jdMenuHide();
})
.bind('unload', function() {
$(jdMenu).each(function() {
this.$settings = null;
});
});
$.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
};
$.fn.parentsUntil = function(match) {
var a = [];
$(this[0]).parents().each(function() {
a.push(this);
return !$(this).is(match);
});
return this.pushStack(a, arguments);
};
function getSettings(el) {
return $(el).parents('ul.jd_menu_flag_root')[0].$settings;
};
function addEvents(ul) {
removeEvents(ul);
$('> li', ul)
.hover(hoverOverLI, hoverOutLI)
.bind('click', itemClick)
.find('> a.accessible')
.bind('click', accessibleClick);
};
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);
}
if ($('> ul', this).size() > 0) {
var settings = getSettings(this);
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() {
$(this)	.removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar')
.find('> a')
.removeClass('jd_menu_hover').removeClass('jd_menu_hover_menubar');
if (this.$timer) {
clearTimeout(this.$timer);
}
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 showMenuLI() {
var ul = $('> ul', this).get(0);
if ($(ul).is(':visible')) {
return false;
}
if (this.$timer) {
clearTimeout(this.$timer);
}
var settings = getSettings(this);
if (settings.onShow != null && settings.onShow.apply(this) == false) {
return false;
}
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) {
var c = 'jd_menu_active' + ($(this).parent().parent().parent().is('.jd_menu_flag_root') ? '_menubar' : '');
$(this).parent().parent().addClass(c).find('> a').addClass(c);
}
$(this).parent().find('> li > ul:visible').not(ul).each(function() {
hideMenuUL.apply(this);
});
addEvents(ul);
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;
};
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);
$(ul).css({visibility: 'hidden', left: 0, top: 0}).show();
var menuWidth		= $(ul).outerWidth();
var menuHeight		= $(ul).outerHeight();
var tp 				= $(this).parent();
var thisWidth		= tp.outerWidth();
var thisBorderWidth	= parseInt(tp.css('borderLeftWidth')) + parseInt(tp.css('borderRightWidth'));
var thisHeight		= $(this).outerHeight();
var thisOffset 		= $(this).offset({border: false});
$(ul).hide().css({visibility: ''});
var position = [];
position[0] = new Range(thisOffset.left, thisOffset.left + menuWidth,
thisOffset.top + thisHeight, thisOffset.top + thisHeight + menuHeight);
position[1] = new Range((thisOffset.left + thisWidth) - menuWidth, thisOffset.left + thisWidth,
position[0].y1, position[0].y2);
position[2] = position[0].nudgeX(viewport);
position[3] = new Range(thisOffset.left + thisWidth - thisBorderWidth, thisOffset.left + thisWidth - thisBorderWidth + menuWidth,
thisOffset.top, thisOffset.top + menuHeight);
position[4] = new Range(position[3].x1, position[3].x2,
position[0].y1 - menuHeight, position[0].y1);
position[5] = position[3].nudgeY(viewport);
position[6] = new Range(thisOffset.left, thisOffset.left + menuWidth,
thisOffset.top - menuHeight, thisOffset.top);
position[7] = new Range((thisOffset.left + thisWidth) - menuWidth, thisOffset.left + thisWidth,
position[6].y1, position[6].y2);
position[8] = position[6].nudgeX(viewport);
position[9] = new Range(thisOffset.left - menuWidth, thisOffset.left,
position[3].y1, position[3].y2);
position[10]= new Range(position[9].x1, position[9].x2,
position[4].y1 + thisHeight - menuHeight, position[4].y1 + thisHeight);
position[11]= position[10].nudgeY(viewport);
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];
}
var pos = order[0];
for (var i = 0, j = order.length; i < j; i++) {
if (viewport.contains(position[order[i]])) {
pos = order[i];
break;
}
}
var menuPosition = position[pos];
$(this).add($(this).parents()).each(function() {
if ($(this).css('position') == 'absolute') {
var abs = $(this).offset();
menuPosition = menuPosition.transform(-abs.left, -abs.top);
return false;
}
});
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});
settings.onAnimate.apply(ul, [true]);
} else {
$(ul).css({left: menuPosition.x1, top: menuPosition.y1}).show();
}
return true;
};
function hideMenuUL(recurse) {
if (!$(this).is(':visible')) {
return false;
}
var settings = getSettings(this);
if (settings.onHideCheck != null && settings.onHideCheck.apply(this) == false) {
return false;
}
$('> li ul:visible', this).each(function() {
hideMenuUL.apply(this, [false]);
});
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();
if (settings.onHide != null) {
settings.onHide.apply(this);
}
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;
};
function accessibleClick(e) {
if ($(this).is('.accessible')) {
e.preventDefault();
}
};
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);