📄 jquery.mcdropdown.js
字号:
// if IE6, add the hover class
$(this).addClass("mc_hover");
// show the branch
$.data(self, "timer", setTimeout(function(){
showBranch.apply(self);
}, settings.hoverOverDelay)
);
};
function hoverOut(e){
var self = this;
var timer = $.data(self, "timer");
// if the timer exists, clear it
if( !isNaN(timer) ) clearTimeout(timer);
// if IE6, remove the hover class
$(this).removeClass("mc_hover");
// hide the branch
$.data(self, "timer", setTimeout(function(){
var $li = $(self);
setTimeout(function (){
// if no children selected, we must close the parent menus
if( $li.parent().find("> li.mc_hover").length == 0 ){
$li.parents("li").each(function (){
var self = this;
clearTimeout($.data(self, "timer"));
hideBranch.apply(self);
// check to see if we've hovered over a parent item
if( $(this).siblings().filter(".mc_hover").length > 0 ) return false;
});
}
}, settings.hoverOverDelay);
hideBranch.apply(self);
}, settings.hoverOutDelay)
);
// this will stop flickering in IE6, but it leaves mc_hover classes behind
if( isIE6 ) e.stopPropagation();
};
function getShadow(depth){
var shadows = $self.data("shadows");
// if the shadows don't exist, create an object to track them
if( !shadows )
shadows = {};
// if the shadow doesn't exist, create it
if( !shadows[depth] ){
// create shadow
shadows[depth] = $('<div class="mcdropdown_shadow"></div>').appendTo('body');
// if the bgIframe exists, use the plug-in
if( !!$.fn.bgIframe ) shadows[depth].bgIframe();
// update the shadows cache
$self.data("shadows", shadows);
}
return shadows[depth];
};
function showBranch(){
var self = this;
// the child menu
var $ul = $("> ul", this);
// if the menu is already visible or there is no submenu, cancel
if( $ul.is(":visible") || ($ul.length == 0) ) return false;
// hide any visible sibling menus
$(this).parent().find('> li ul:visible').not($ul).parent().each(function(){
hideBranch.apply(this);
});
// columnize the list
columnizeList($ul);
// add new bindings
addBindings($ul);
var depth = $ul.parents("ul").length;
// get the screen dimensions
var sd = getScreenDimensions();
// get the coordinates for the menu item
var li_coords = position($(this));
// move the menu to the correct position and show the menu || ((depth)*2)
$ul.css({top: li_coords.bottom, left: li_coords.marginLeft/*, zIndex: settings.baseZIndex + ((depth)*2)*/}).show();
// get the bottom of the menu
var menuBottom = $ul.outerHeight() + $ul.offset().top;
// if we're hidden off the bottom of the page, move up
if( menuBottom > sd.y ){
// adjust the menu by subtracting the bottom edge by the screen offset
$ul.css("top", li_coords.bottom - (menuBottom - sd.y) - settings.screenPadding);
}
var showShadow = function (){
// if using drop shadows, then show them
if( settings.dropShadow ){
// get a reference to the current shadow
var $shadow = getShadow(depth);
// get the position of the parent element
var pos = position($ul);
// move the shadow to the correct visual & DOM position
$shadow.css({
top: pos.top + pos.marginTop
, left: pos.left + pos.marginLeft
, width: pos.width
, height: pos.height
/*, zIndex: settings.baseZIndex + ((2*depth)-1)*/
}).insertAfter($ul).show();
// store a reference to the shadow so we can hide it
$.data(self, "shadow", $shadow);
}
}
// columnize the list and then show it using the defined effect
// if the menu has a zero delay, just open it and then draw the
// shadow, otherwise show the effect and the draw the shadow
// after you're done.
if( settings.showSpeed <= 0 ){
showShadow();
} else {
$ul.hide()[settings.showFx](settings.showSpeed, showShadow);
}
};
function hideBranch(){
var $ul = $("> ul", this);
// if the menu is already visible or there is no submenu, cancel
if( $ul.is(":hidden") || ($ul.length == 0) ) return false;
// if using drop shadows, then hide
if( settings.dropShadow && $.data(this, "shadow") ) $.data(this, "shadow").hide();
// if we're IE6, we need to set the visiblity to "hidden" so child
// menus are correctly hidden and remove the .mc_hover class due to
// the e.stopPropagation() call in the hoverOut() call
if( isIE6 )
$ul.css("visibility", "hidden").parent().removeClass("mc_hover");
// hide the menu
$ul.stop()[settings.hideFx](settings.hideSpeed);
};
function position($el){
var bHidden = false;
// if the element is hidden we must make it visible to the DOM to get
if ($el.is(":hidden")) {
bHidden = !!$el.css("visibility", "hidden").show();
}
var pos = $.extend($el.position(),{
width: $el.outerWidth()
, height: $el.outerHeight()
, marginLeft: parseInt($.curCSS($el[0], "marginLeft", true), 10) || 0
, marginRight: parseInt($.curCSS($el[0], "marginRight", true), 10) || 0
, marginTop: parseInt($.curCSS($el[0], "marginTop", true), 10) || 0
, marginBottom: parseInt($.curCSS($el[0], "marginBottom", true), 10) || 0
});
if( pos.marginTop < 0 ) pos.top += pos.marginTop;
if( pos.marginLeft < 0 ) pos.left += pos.marginLeft;
pos["bottom"] = pos.top + pos.height;
pos["right"] = pos.left + pos.width;
// hide the element again
if( bHidden ) $el.hide().css("visibility", "visible");
return pos;
};
function anchorTo($anchor, $target){
var pos = position($anchor);
$target.css({
position: "absolute"
, top: pos.bottom
, left: pos.left
});
/*
* we need to return the top edge of the core drop down menu, because
* the top:0 starts at this point when repositioning items absolutely
* this means we have to offset everything by the offset of the top menu
*/
return pos.bottom;
};
function getScreenDimensions(){
var d = {
scrollLeft: $(window).scrollLeft()
, scrollTop: $(window).scrollTop()
, width: $(window).width() // changed from innerWidth
, height: $(window).height() // changed from innerHeight
};
// calculate the correct x/y positions
d.x = d.scrollLeft + d.width;
d.y = d.scrollTop + d.height;
return d;
};
function getPadding(el, name){
var torl = name == 'height' ? 'Top' : 'Left', // top or left
borr = name == 'height' ? 'Bottom' : 'Right'; // bottom or right
return (
// we add "0" to each string to make sure parseInt() returns a number
parseInt("0"+$.curCSS(el, "border"+torl+"Width", true), 10)
+ parseInt("0"+$.curCSS(el, "border"+borr+"Width", true), 10)
+ parseInt("0"+$.curCSS(el, "padding"+torl, true), 10)
+ parseInt("0"+$.curCSS(el, "padding"+borr, true), 10)
+ parseInt("0"+$.curCSS(el, "margin"+torl, true), 10)
+ parseInt("0"+$.curCSS(el, "margin"+borr, true), 10)
);
};
function getListDimensions($el, cols){
if( !$el.data("dimensions") ){
// get the width of the dropdown menu
var ddWidth = $divInput.outerWidth();
// if showing the root item, then try to make sure the width of the menu is sized to the drop down menu
var width = ( ($el === $list) && ($el.data("width") * cols < ddWidth) ) ? Math.floor(ddWidth/cols) : $el.data("width");
$el.data("dimensions", {
// get the original width of the list item
column: width
// subtract the padding from the first list item from the width to get the width of the items
, item: width - getPadding($el.children().eq(0)[0], "width")
// get the original height
, height: $el.height()
});
}
return $el.data("dimensions");
};
function getHeight($el){
// if we haven't cached our height, do so now
if( !$el.data("height") ) $el.data("height", $el.outerHeight());
// return the cached value
return $el.data("height");
};
function columnizeList($el){
// get the children items
var $children = $el.find("> li");
// get the total number of items
var items = $children.length;
// calculate how many columns we think we should have based on the max rows
var calculatedCols = Math.ceil(items/settings.maxRows);
// get the number of columns, don't columnize if we don't have enough rows
// if the height of the column is bigger than the screen, we automatically try
// moving to a new column
var cols = !!arguments[1] ? arguments[1] : ( items <= settings.minRows ) ? 1 : (calculatedCols > settings.targetColumnSize) ? calculatedCols : settings.targetColumnSize;
// get the dimension of this element
var widths = getListDimensions($el, cols);
var prevColumn = 0;
var columnHeight = 0;
var maxColumnHeight = 0;
var maxRows = Math.ceil(items/cols);
// get the width of the parent item
var parentLIWidth = $el.parent("li").width();
// if the parent list item is wider than the child menu, increase the size
if( parentLIWidth > (widths.column * cols) ){
// get the difference in the widths so we can adjust
var widthDiff = parentLIWidth - widths.column;
widths.column += parentLIWidth;
widths.item += widthDiff;
}
// we need to draw the list element, but hide it so we can correctly calculate it's information
$el.css({"visibility": "hidden", "display": "block"});
// loop through each child item
$children.each(function (i){
var currentItem = i+1;
var nextItemColumn = Math.floor((currentItem/items) * cols);
// calculate the column we're in
var column = Math.floor((i/items) * cols);
// reference the current item
var $li = $(this);
// variable to track margin-top
var marginTop;
// if we're in the same column
if( prevColumn != column ){
// move to the top of the next column
marginTop = (columnHeight+1) * -1;
// reset column height
columnHeight = 0;
// if we're in a new column
} else {
marginTop = 0;
}
// increase the column height based on it's current height (calculate this before adding classes)
columnHeight += (getHeight($li) || settings.lineHeight);
// update the css settings
$li.css({
"marginLeft": (widths.column * column)
, "marginTop": marginTop
, "width": widths.item
})
[((nextItemColumn > column) || (currentItem == items)) ? "addClass" : "removeClass"]("mc_endcol")
[(marginTop != 0) ? "addClass" : "removeClass"]("mc_firstrow")
;
// get the height of the longest column
if( columnHeight > maxColumnHeight ) maxColumnHeight = columnHeight;
// update the previous column
prevColumn = column;
});
/*
* this would work on resize the main column
var s = ($el === $list) ? maxColumnHeight + $divInput.offset().top + $divInput.outerHeight() : maxColumnHeight;
*/
// if the menu is too tall to fit on the screen, try adding another column
if( ($el !== $list) && (maxColumnHeight + (settings.screenPadding*2) >= getScreenDimensions().height) ){
return columnizeList($el, cols+1);
}
/*
* set the height of the list to the max column height. this fixes
* display problems in FF when the last column is not full.
*
* we also need to set the visiblity to "visible" to make sure that
* the element will show up
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -