以下是 jQuery无序列表的下拉菜单特效代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>jQuery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></meta>
<script src="js/jqmin.1.10.1.js" type="text/javascript"></script>
<script src="js/jquery.hoverintent.r7.js" type="text/javascript"></script>
<script src="js/jquery.mnmenu.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$('#idmenu').mnmenu();
//Create and init additional menus
var $demoContainer = $('#demoContainer');
$demoContainer.append($("<h3>Regular menus</h3>"));
$demoContainer.append($("<p>Menus with different colors and styling.</p>"));
//Create lists
$(["bluemenu", "grayround", "squarewhite", "blue2menu"]).each(function () {
var color = this;
var $temp = generateMenu(color);
$demoContainer.append($temp);
$temp.mnmenu({ menuClassName: color.toString() });
});
$demoContainer.append($(["<h3>Right aligned menu</h3>"].join("")));
$demoContainer.append($("<p>This menu is the reversed version of the top menu."
+ " Menus will be displayed from bottom to top and from right to left.</p>"));
//Init right to left menu with custom level settings
var rightMenuLevelSettings = {};
//Defaults
rightMenuLevelSettings[0] = new MNLevelSettings();
rightMenuLevelSettings[0].parentAttachmentPosition = "SW";
rightMenuLevelSettings[0].attachmentPosition = "SE";
//First level
rightMenuLevelSettings[1] = new MNLevelSettings();
rightMenuLevelSettings[1].parentAttachmentPosition = "NE";
rightMenuLevelSettings[1].attachmentPosition = "SE";
var $rightbtmenu = generateMenu("rightbtmenu");
$demoContainer.append($rightbtmenu);
$rightbtmenu.mnmenu({ menuClassName: "rightbtmenu", levelSettings: rightMenuLevelSettings });
/////////////////////////////////////////////////////
function generateMenu(id) {
var $temp = $(["<ul id='", id, "'></ul>"].join(""));
//ADD Submenus
for (var i = 1; i < 6; i++) {
var label = ["Level-", i].join("");
var $firstLevel = $(["<li>", label, "</li>"].join(""));
$temp.append($firstLevel);
addLevels(1, 5, $firstLevel, label);
}
return $temp;
}
function addLevels(current, max, $component, label) {
var $newContainer = null;
for (var i = 1; i < Math.floor(Math.random() * 6) + 1; i++) {
if ($newContainer === null) {
$newContainer = $("<ul></ul>");
$component.append($newContainer);
}
var newLabel = [label, "-", i].join("");
var $newLevel = $(["<li>", newLabel, "</li>"].join(""));
$newContainer.append($newLevel);
if (current < max) {
addLevels(current + 1, max, $newLevel, newLabel);
}
}
}
});</script>
<link href="css/styleIE.css" type="text/css" rel="stylesheet" />
<link href="css/blue.css" type="text/css" rel="stylesheet" />
<link href="css/grayround.css" type="text/css" rel="stylesheet" />
<link href="css/squarewhite.css" type="text/css" rel="stylesheet" />
<link href="css/blue2.css" type="text/css" rel="stylesheet" />
<link href="css/rightbt.css" type="text/css" rel="stylesheet" />
</head>
<body>
<ul id="idmenu">
<li>
<a href="#" id="idTestLink"><span>File</span></a>
<ul>
<li><a href="#"><span>New</span></a></li>
<li><a href="#"><span>Open</span></a></li>
<li>
<a href="#"><span>Open Recent</span></a>
<ul>
<li>/home/user/documents/mnmenu-userguide.pdf</li>
<li>/home/user/documents/TakingOverTheWorldIn10days.pdf</li>
<li>/home/user/documents/WorldDominationForDummies.pdf</li>
<li>/home/user/documents/HowToUninstallWindows.pdf</li>
</ul>
</li>
<li><hr /></hr></li>
<li><a href="#"><span>Save</span></a></li>
<li><a href="#"><span>Save as...</span></a></li>
<li><a href="#"><span>Quit</span></a></li>
</ul>
</li>
<li>
<a href="#" id="id31"><span>Sales</span></a>
<ul>
<span>
<li><a href="#" id="id32"><span>Accounts</span></a></li>
<li><a href="#" id="id33"><span>Companies</span></a></li>
<li><a href="#" id="id34"><span>Leads</span></a></li>
<li>
<a href="#" id="id35"><span>Activities</span></a>
<ul>
<li><a href="#" id="id36"><span>Calls</span></a></li>
<li><a href="#" id="id37"><span>Tasks</span></a></li>
<li><a href="#" id="id38"><span>Meetings</span></a></li>
</ul>
</li>
</span>
</ul>
</li>
<li>
<a href="#" id="id39"><span>Master</span></a>
<ul>
<li> <a href="#" id="id3a"><span>Company</span></a></li>
<li>
<a href="#" id="id3b"><span>System</span></a>
<ul>
<li>
<a href="#" id="id3c"><span>Places</span></a>
<ul>
<li><a href="#" id="id3d"><span>Countries</span></a></li>
<li><a href="#" id="id3e"><span>States</span></a></li>
<li><a href="#" id="id3f"><span>Postal Codes</span></a></li>
</ul>
</li>
<li><a href="#" id="id40"><span>Currency</span></a></li>
<li><a href="#" id="id41"><span>Taxes</span></a></li>
<li><a href="#" id="id42"><span>Invoice Series</span></a></li>
</ul>
</li>
<li>
<a href="#" id="id43"><span>Issues</span></a>
<ul>
<li><a href="#" id="id44"><span>Types</span></a></li>
<li><a href="#" id="id45"><span>Solutions</span></a></li>
</ul>
</li>
<li><a href="#" id="id46"><span>Users</span></a></li>
</ul>
</li>
<li>
<a href="#">Menu</a>
<ul>
<li><a href="#">Level M-1</a></li>
<li><a href="#">Level M-2</a></li>
<li><a href="#">Level M-3</a></li>
<li><a href="#">Level M-4</a></li>
<li><a href="#">Level M-5</a></li>
<li>
<a href="#">Level M-6</a>
<ul>
<li><a href="#">Level M-6-1</a></li>
<li><a href="#">Level M-6-2</a></li>
<li><a href="#">Level M-6-3</a></li>
<li><a href="#">Level M-6-4</a></li>
</ul>
</li>
<li><a href="#">Level M-7</a></li>
<li><a href="#">Level M-8</a></li>
<li><a href="#">Level M-9</a></li>
<li><a href="#">Level M-10</a></li>
</ul>
</li>
<li>
<a href="#" id="id47"><span>Web</span></a>
<ul>
<li><a href="#" id="id48"><span>Log</span></a></li>
<li><a href="#" id="id49"><span>Texts</span></a></li>
<li><a href="#" id="id4a"><span>Categories</span></a></li>
<li><a href="#" id="id4b"><span>Articles</span></a></li>
<li><a href="#" id="id4c"><span>Files</span></a></li>
</ul>
</li>
</ul>
<div class="content">
<h2>Demos</h2>
<div id="demoContainer" class="demos">
</div>
<p>
This menus are generated with javascript. To see the structure the menu should
have, you can take a look to the top menu which is static.
</p>
</div>
</body>
</html>
JS代码(jquery.mnmenu.js):
/** * MNMenu * Drop down menu * * Copyright (c) 2013 Marc Nuri * Version:0.0.15 * Modified:2013-07-25 * Licensed under the MIT license:* http://www.opensource.org/licenses/mit-license.php * * http://www.marcnuri.com */
/** * Main plugin function * * @param{
jQuery}
$ * @returns{
undefined}
*/
(function($){
/** * Plugin initialization function * * @param{
object}
op * @returns{
unresolved}
*/
$.fn.mnmenu = function(op){
//////////////////////////////////////////////////////////////////////// //To specify custom level settings without affecting defaults var tempLevelSettings ={
}
;
if (typeof op !== 'undefined' && typeof op.levelSettings !== 'undefined'){
tempLevelSettings = op.levelSettings;
delete op.levelSettings;
}
//////////////////////////////////////////////////////////////////////// var settings = $.extend({
}
,$.fn.mnmenu.defaults,op);
//////////////////////////////////////////////////////////////////////// //Clone custom level settings so that defaults remain and apply custom;
settings.levelSettings = $.extend({
}
,settings.levelSettings,tempLevelSettings);
//////////////////////////////////////////////////////////////////////// return this.each(function(){
var $parentMenu = $(this);
if ($parentMenu.prop("tagName").toUpperCase() !== "UL"){
$.error("This function can only be called in <ul> elements.");
}
$parentMenu.addClass(settings.menuClassName);
//Recursion through elements to set default class names and parameters $.fn.mnmenu.levelRecursion(settings,$parentMenu,0);
//Hide every other submenu (It should be prehidden by css) $parentMenu.find("ul").each(function(){
$(this).css("display","none");
}
);
//Add event listeners to every LI if ($.fn.hoverIntent){
$parentMenu.find("li").each(function(){
var $this = $(this);
$this.hoverIntent( function(){
$.fn.mnmenu.mouseEnter($(this),settings);
}
,function(){
$.fn.mnmenu.mouseLeave($(this),settings);
}
);
$this.click(function(e){
$.fn.mnmenu.mouseClick($(this),settings);
e.stopImmediatePropagation();
}
);
}
);
}
else{
$parentMenu.find("li").each(function(){
var $this = $(this);
$this.mouseenter(function(){
$.fn.mnmenu.mouseEnter($(this),settings);
}
);
$this.mouseleave(function(){
$.fn.mnmenu.mouseLeave($(this),settings);
}
);
$this.click(function(e){
$.fn.mnmenu.mouseClick($(this),settings);
e.stopImmediatePropagation();
}
);
}
);
}
}
);
}
;
/** * Function called when mouse hovers a menu entry (<
li>
) * @param{
jQuery}
$menu * @param{
type}
settings * @returns{
undefined}
*/
$.fn.mnmenu.mouseEnter = function($menu,settings){
var windowWidth = $(window).width();
clearTimeout($menu.data('timer'));
//Add hover class $.fn.mnmenu.elementsToHover($menu,settings).each(function(){
$(this).addClass(settings.hoverClassName);
}
);
$menu.children("ul").each(function(){
var $this = $(this);
var $parent = $this.parent("li");
var $parentContainer = $parent.closest("ul");
//Stop previous (hiding) animation and display the object //Calculations had already been made if ($this.is(":animated")){
$this.stop(true,true).show();
}
//Was hidden else{
//Set Z-Index var zindex = 1;
var current = $this;
while (current.get(0) !== $(document).get(0)){
var temp = parseInt(current.css("z-index"));
if (!isNaN(temp) && temp > zindex){
zindex = temp;
}
current = current.parent();
}
$this.css("z-index",zindex + 1);
//Calculate+set container position // - Find level var currentLevel = 0;
var classList = $this[0].className.split(/\s+/);
for (var i = 0;
i < classList.length;
i++){
if (classList[i].indexOf([settings.levelClassPrefix,'-'].join('')) >= 0){
currentLevel = parseInt(classList[i].substring(settings.levelClassPrefix.length + 1));
}
}
var customLevelSettings = settings.levelSettings[currentLevel];
if (typeof customLevelSettings === "undefined"){
customLevelSettings = settings.levelSettings[0];
}
//Horizontal position var left = "auto",right = "auto",top = "auto",bottom = "auto";
//RtL if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("W") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("E") >= 0){
right = $parent.outerWidth() + "px";
//Always show on screen (Reversi) if ($parent.offset().left - $this.outerWidth() < 0){
left = $parent.outerWidth() + "px";
right = "auto";
}
}
else if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("E") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("E") >= 0){
right = "0px";
}
//LtR else if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("E") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("W") >= 0){
left = $parent.outerWidth() + "px";
//Always show on screen (Reversi) if (($parentContainer.offset().left + $parentContainer.outerWidth() + $this.outerWidth()) > windowWidth){
left = "auto";
right = $parent.outerWidth() + "px";
}
}
else if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("W") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("W") >= 0){
left = "0px";
}
//Vertical Position if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("N") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("S") >= 0){
bottom = $parent.outerHeight() + "px";
}
else if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("S") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("S") >= 0){
bottom = "0px";
}
else if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("S") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("N") >= 0){
top = $parent.outerHeight() + "px";
}
else if (customLevelSettings.parentAttachmentPosition.toUpperCase().indexOf("N") >= 0 && customLevelSettings.attachmentPosition.toUpperCase().indexOf("N") >= 0){
top = "0px";
}
$this.css("left",left);
$this.css("right",right);
$this.css("top",top);
$this.css("bottom",bottom);
// OLD WAY////////////////////////////////////////////////////////////////////////////////// //Position forNon-level-0 elements// if (!$parent.hasClass(// [settings.levelClassPrefix,"-0"].join(""))){
// //Horizontal position// var initialOffset = $parentContainer.offset().left +// $parentContainer.outerWidth();
// if (windowWidth < (initialOffset + $this.outerWidth())){
// $this.css("left","auto");
// $this.css("right",(// //Container// ($parentContainer.outerWidth())// //Padding// + ($this.outerWidth() - $this.innerWidth())// ) + "px");
//}
else{
// $this.css("left",$parentContainer.outerWidth() + "px");
// $this.css("right","auto");
//}
// //Vertical position// if ($parent.css("position") === "relative"){
// $this.css("top","0px");
//}
else{
// $this.css("top",$parent.position().top + "px");
//}
//}
// //level-0 elements// else{
// $this.css("left","0px");
// $this.css("top",$this.closest("li").outerHeight() + "px");
//}
//////////////////////////////////////////////////////////////////////////////// $this.slideDown(settings.duration);
}
}
);
}
;
/** * Function called when mouse leaves a menu entry (<
li>
) * @param{
jQuery}
$menu * @param{
type}
settings * @returns{
undefined}
*/
$.fn.mnmenu.mouseLeave = function($menu,settings){
clearTimeout($menu.data('timer'));
//Remove hover class $.fn.mnmenu.elementsToHover($menu,settings).each(function(){
$(this).removeClass(settings.hoverClassName);
}
);
$menu.children("ul").each(function(){
var $toHide = $(this);
$menu.data('timer',setTimeout( function(){
$toHide.hide(settings.duration);
}
,settings.delay));
}
);
}
;
/** * Function called when mouse clicks a menu entry (<
li>
) * @param{
jQuery}
$menu * @param{
type}
settings * @returns{
undefined}
*/
$.fn.mnmenu.mouseClick = function($menu,settings){
//Contribution by https://github.com/akcoder //TODO:Rething function to adad customization capabilities (Ajax links,support for href target...) clearTimeout($menu.data('timer'));
var $link = $menu.children('a');
if ($link.attr('href')){
window.location.href = $link.attr('href');
}
}
;
/** * Returns an array of elements to which to add/remove the "hover" * class when hovered * @param{
jQuery}
$menu * @param{
type}
settings * @returns{
jQuery}
*/
$.fn.mnmenu.elementsToHover = function($menu,settings){
//All children which aren't containers (li,span,links...) //This makes it easier for styling. return $([$menu,$menu.children(":not(ul)")]);
}
;
/** * Recursive function to traverse the component hierarchy setting attributes * and adding the rest of components such as arrows. * * @param{
type}
settings * @param{
jQuery}
$component * @param{
int}
level * @returns{
undefined}
*/
$.fn.mnmenu.levelRecursion = function(settings,$component,level){
if ($component.prop("tagName").toUpperCase() === "LI"){
var middle = true;
//Add arrows to parent <li>. This can only happen from level 1 if ($component.parent().children().first().get(0) === $component.get(0) && level > 0){
//Add Arrow to parent (just once). $component.parent().closest("li").append( $(["<span ","class='",settings.arrowClassName,"'></span>"].join("") ).append(settings.arrowCharacter));
//Add FirstClassName to first <li> $component.addClass(settings.firstClassName);
middle = false;
}
//component can be first and last (no else if) if ($component.parent().children().last().get(0) === $component.get(0)){
$component.addClass(settings.lastClassName);
middle = false;
}
if (middle){
$component.addClass(settings.middleClassName);
}
level++;
}
//The component may not have 'li' direct descendants a span or something else may be in the way $component.children().each(function(){
var $currentLevel = $(this);
$currentLevel.addClass(settings.levelClassPrefix + "-" + level);
$.fn.mnmenu.levelRecursion(settings,$currentLevel,level);
}
);
}
;
/** * Default plugin options */
$.fn.mnmenu.defaults ={
//Class for top-level menuName menuClassName:"mnmenu",//Class for hovered elements hoverClassName:"hover",//List elements levels levelClassPrefix:"level",//Class for arrow <span> arrowClassName:"arrow",arrowCharacter:" »
",//List elements position in level firstClassName:"first",middleClassName:"middle",lastClassName:"last",delay:150,duration:250,defaultParentAttachmentPosition:"NE",defaultAttachmentPosition:"NW"}
;
$.fn.mnmenu.defaults.levelSettings ={
}
;
//Define defaultTopLevelSettings $.fn.mnmenu.defaults.levelSettings[0] = new MNLevelSettings();
//Second level settings for default behavior (typical menu) $.fn.mnmenu.defaults.levelSettings[1] = new MNLevelSettings();
$.fn.mnmenu.defaults.levelSettings[1].parentAttachmentPosition = "SW";
$.fn.mnmenu.defaults.levelSettings[1].attachmentPosition = "NW";
}
)(jQuery);
function MNLevelSettings(){
this.parentAttachmentPosition = $.fn.mnmenu.defaults.defaultParentAttachmentPosition;
this.attachmentPosition = $.fn.mnmenu.defaults.defaultAttachmentPosition;
this.arrowCharacter = $.fn.mnmenu.defaults.arrowCharacter;
}
CSS代码(rightbt.css):
/* Document:right.css Created on:Jun 19,2013,13:31:00 Author:Marc Nuri <marc@marcnuri.com> Description:Stylesheet for Right aligned menu*/
ul.rightbtmenu{margin:10px 0 0 0;padding:0;list-style:none;text-align:right;}
ul.rightbtmenu{font-size:0px;line-height:25px;clear:both;background:#777777 url('menuLight.png') repeat-x 50% 50%;}
ul.rightbtmenu li{font-size:13px;list-style:none;text-align:right;}
ul.rightbtmenu a{padding:0;text-decoration:none;}
ul.rightbtmenu li.level-0{position:relative;display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;min-height:25px;line-height:25px;height:25px;_height:25px;vertical-align:top;padding:0 25px 0 10px;border-left:1px solid #222222;}
ul.rightbtmenu li.level-0 a,ul.rightbtmenu li.level-0 a:visited{color:black;}
ul.rightbtmenu li.level-0.hover a{color:white;}
ul.rightbtmenu li.level-0.first{border-left:none;}
ul.rightbtmenu li.level-0.hover{background:#333333 url('menuDark.png') repeat-x 50% 50%;outline:0;}
ul.rightbtmenu li.level-0 ul{position:absolute;display:none;margin:0;padding:0;background-color:#333;width:10em;-webkit-box-shadow:0px -2px 6px 1px #222;box-shadow:0px -2px 6px 1px #222;}
ul.rightbtmenu li.level-0 li{position:relative;width:9em;padding:0 0.5em 0 0.5em;display:block;float:right;}
ul.rightbtmenu li.level-0 li.middle{margin:5px 0 5px 0;}
ul.rightbtmenu li.level-0 li,ul.rightbtmenu li.level-0 li a,ul.rightbtmenu li.level-0 li a:visited{color:white;word-break:break-all;}
ul.rightbtmenu li.level-0 li.hover{background:#666;outline:0;}
/* ARROWS */
ul.rightbtmenu li.level-0 span.arrow{position:absolute;overflow:hidden;text-indent:9999em;top:6px;right:7px;width:10px;background:transparent url('menuArrowsCWFFFFFF.png') no-repeat -10px 0px;}
ul.rightbtmenu li.level-0 span.arrow.hover{background:transparent url('menuArrowsCWFFFFFF.png') no-repeat 0px 0px;}
ul.rightbtmenu li.level-0 li span.arrow{right:auto;left:7px;background:transparent url('menuArrowsCWFFFFFF.png') no-repeat -10px -100px;}
ul.rightbtmenu li.level-0 li span.arrow.hover{background:transparent url('menuArrowsCWFFFFFF.png') no-repeat 0px -100px;}
/** NON-MENU OTHER **/
ul.rightbtmenu hr,ul.rightbtmenu li.level-0 li hr{border:0;color:#555;background-color:#555;height:1px;}
body,input,select,textarea,button{font:13px Helvetica,arial,freesans,clean,sans-serif;line-height:1.4;}
div.content{margin:5px;}
.content{font-size:15px;line-height:1.7;color:#333333;}
.content h1{font-size:2.5em;}
.content h2{font-size:2em;border-bottom:1px solid #eee;}
.content a{color:#4183c4;text-decoration:none;}
.content a:hover{text-decoration:underline;}
.content p{margin:15px 0;}
div.copyright{margin:100px 0 0 0;}
CSS代码(squarewhite.css):
/* Document:squarewhite.css Created on:Jun 13,2013,17:26:35 Author:Marc Nuri <marc@marcnuri.com> Description:Stylesheet for mnmenu examples*/
ul.squarewhite{margin:0;padding:0;list-style:none;display:block;margin-top:15px;height:80px;background:#fff;border:1px solid #cecece;margin-bottom:17px;-webkit-box-shadow:0 0 6px rgba(0,0,0,.12);-moz-box-shadow:0 0 6px rgba(0,0,0,.12);-o-box-shadow:0 0 6px rgba(0,0,0,.12);box-shadow:0 0 6px rgba(0,0,0,.12);color:#444444;}
ul.squarewhite li.level-0{position:relative;display:-moz-inline-stack;display:inline-block;*display:inline;vertical-align:top;zoom:1;min-height:50px;line-height:50px;height:50px;_height:50px;font-family:Helvetica,Arial,Verdana,sans-serif;font-size:20px;margin:0;padding:15px 30px 15px 30px;}
ul.squarewhite li.level-0.hover{border-top:3px solid #000;border-bottom:3px solid white;-webkit-box-shadow:0 0 5px rgba(0,0,0,.22);-moz-box-shadow:0 0 5px rgba(0,0,0,.22);-o-box-shadow:0 0 5px rgba(0,0,0,.22);box-shadow:0 0 5px rgba(0,0,0,.22);padding:12px 30px 15px 30px;color:black;}
ul.squarewhite li.level-0 ul{position:absolute;display:none;margin:-5px 0 0 -1px;padding:0;width:15em;background:#fff;border:solid #cecece;border-width:0px 1px 1px 1px;-webkit-box-shadow:2px 3px 8px rgba(0,0,0,.22);-moz-box-shadow:2px 3px 8px rgba(0,0,0,.22);-o-box-shadow:2px 3px 8px rgba(0,0,0,.22);box-shadow:2px 3px 8px rgba(0,0,0,.22);}
ul.squarewhite li.level-0 li{position:relative;filter:none;color:#444444;font-size:14px;display:block;line-height:28px;padding:10px;}
ul.squarewhite li.level-0 li.first,ul.squarewhite li.level-0 li.middle{border-bottom:1px solid #cecece;}
ul.squarewhite li.level-0 li.last{border-bottom:none;}
ul.squarewhite li.level-0 li.hover{background-color:#68B00C;color:white;}
ul.squarewhite li.level-1 ul{margin:0 0 0 -3px;}
ul.squarewhite span.arrow{display:none;}