特点:
1.根据自定义菜单结构生成菜单;
2.多级联动功能;
3.自定义浮动位置(上下左右);
4.自定义延迟效果;
5.js控制编辑菜单;
6.可根据需要自动生产容器对象;
也有一些要求和问题,例如样式有些要求,位置取不准等。
参数1是容器列表:
var arrContainer=["idMenu1"];
如果定义的容器少于需要的容器,会自动根据最后一个对象生产新的容器,并继承其样式。
例如这里需要5个容器,但只定义了一个容器,后面就会根据需要生产新的容器对象。
当然至少要定义一个容器,不然程序不会执行。
参数2是一个菜单结构:
Code
var arrMenu = [
{'txt': '1 <a href="http://shundebk.cn/">link</a>' },
{'txt': '2 →', 'menu': [
{'txt': '2_1'},
{'txt': '2_2'}
]},
{'txt': '3 →', 'menu': [
{'txt': '3_1 ↑', 'position': 'up', 'menu': [
{'txt': '3_1_1'},
{'txt': '3_1_2'}
]}
]},
{'txt': '4 →', 'menu': [
{'txt': '4_1 ↓', 'position': 'down', 'menu': [
{'txt': '4_1_1 →', 'menu': [
{'txt': '4_1_1_1'}
]}
]}
]},
{'txt': '5 →', 'menu': [
{'txt': '5_1 →', 'menu': [
{'txt': '5_1_1 ↓', 'position': 'down', 'menu': [
{'txt': '5_1_1_1 ←', 'position': 'left', 'menu': [
{'txt': '5_1_1_1_1'}
]}
]}
]}
]}
];
其实是一个数组,数组里面是菜单数据:
txt:菜单显示信息,可以是html;
position:浮动位置,可以是"right"(默认),"down","up","left";
menu:下一级的菜单对象;
参数3是一些设置:
{ Delay: 200, onClass: "on" }
还可以设置:
Position: 默认位置(up,down,left,right);
Tag: 默认生成标签;
Class: 默认样式;
onClass: 焦点样式;
Delay: 延迟值(微秒);
实例化对象:
new CascadeMenu(arrContainer, arrMenu, { Delay: 200, onClass: "on" });
暂时有这些方法:
Add(menu):添加菜单,参数是一个菜单结构
Delete(index):删除菜单,参数是菜单索引
源码:
Code
var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
function addEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.addEventListener) {
oTarget.addEventListener(sEventType, fnHandler, false);
} else if (oTarget.attachEvent) {
oTarget.attachEvent("on" + sEventType, fnHandler);
} else {
oTarget["on" + sEventType] = fnHandler;
}
};
function Event(e){
var oEvent = document.all ? window.event : e;
if (document.all) {
if(oEvent.type == "mouseout") {
oEvent.relatedTarget = oEvent.toElement;
}else if(oEvent.type == "mouseover") {
oEvent.relatedTarget = oEvent.fromElement;
}
oEvent.stopPropagation = function() { this.cancelBubble = true; }
}
return oEvent;
}
function Each(list, fun){
for (var i = 0, len = list.length; i < len; i++) { fun(list
, i); }
};
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
var CascadeMenu = Class.create();
CascadeMenu.prototype = {
//初始化对象(容器集合, 菜单对象)
initialize: function(arrContainer, arrMenu, options) {
if(arrContainer.length <= 0 || arrMenu.lenght <= 0) return;
var oThis = this;
this._timerContainer = null;
this._timerMenu = null;
this._onmenu = null;//当前菜单对象
this._index = -1;//要设置容器的索引
this.Container = [];//容器集合
this.Menu = arrMenu;//菜单对象
this.SetOptions(options);
this.Position = this.options.Position || "right";
this.Delay = parseInt(this.options.Delay) || 0;
this.Class = this.options.Class || "";
this.onClass = this.options.onClass || this.Class;
this.Tag = this.options.Tag;
//设置容器
Each(arrContainer, function(o, i){ oThis.IniContainer(oThis.Container = (o = $(o)), i > 0); });
this.Ini();
},
//设置默认属性
SetOptions: function(options) {
this.options = {//默认值
Position: "right",//默认位置(up,down,left,right)
Tag: "div",//默认生成标签
Class: "",//默认样式
onClass: "",//焦点样式
Delay: 0//延迟值(微秒)
};
Object.extend(this.options, options || {});
},
//初始化容器(容器对象, 是否子菜单)
IniContainer: function(container, bChild) {
var oThis = this;
addEventHandler(container, "mouseover", function(){ clearTimeout(oThis._timerContainer); });
addEventHandler(container, "mouseout", function(e){
var oT = Event(e).relatedTarget;
//是否在菜单之内
var isIn = !!Each(oThis.Container, function(o, i){ if(o.contains ? o.contains(oT) || o == oT : o.compareDocumentPosition(oT) & 16){ return true; } });
//在菜单外隐藏
if(!isIn){
clearTimeout(oThis._timerContainer); clearTimeout(oThis._timerMenu);
oThis._timerContainer = setTimeout(function(){ oThis.Hide(); }, oThis.Delay);
}
});
container.index = -1;
//子菜单设置
if (bChild) { container.style.position = "absolute"; container.style.visibility = "hidden"; }
},
//初始化第一个容器
Ini: function() {
this.Container[0].innerHTML = ""; this._index = 0; this.SetMenu(this.Menu);
},
//全局设置
Set: function() {
//隐藏select
Each(document.getElementsByTagName("select"), function(o){ o.style.visibility = "hidden"; })
var menu = this.Menu
//第一个不需要处理所以从1开始
var i = 1;
while (menu.length > 0) {
//获取菜单和位置
var iC = this.Container[i-1].index, position = this.Position;
if(iC >= 0){
//这里要先取position再设menu
position = menu[iC].position || this.Position; menu = menu[iC].menu || [];
} else { menu = []; }
//如果容器不够就根据前一个自动添加
if(!this.Container){
var oPre = this.Container[i-1], oNew = document.body.appendChild(document.createElement(oPre.tagName));
oNew.style.cssText = oPre.style.cssText; oNew.className = oPre.className;
this.IniContainer(this.Container = oNew, true);
}
if(this._index == i++){
//设置下一级菜单
this.SetContainer(menu, position);
//其他容器隐藏
for(var len = this.Container.length; i < len; i++){ this.Container.style.visibility = "hidden"; }
break;
}
}
},
//容器设置(菜单对象, 位置)
SetContainer: function(menu, position) {
var oContainer = this.Container[this._index];
//设置容器
oContainer.innerHTML = ""; oContainer.index = -1;
if(menu.length <= 0){ oContainer.style.visibility = "hidden"; return; }
this.SetMenu(menu);
//设置位置
//offset取会有偏差(没计边框margin),要注意
var o = this._onmenu, iLeft = o.offsetLeft, iTop = o.offsetTop;
//注意如果display为none的话取不到offset值,所以要用visibility
switch (position.toLowerCase()) {
case "up" :
iTop -= oContainer.offsetHeight;
break;
case "down" :
iTop += o.offsetHeight;
break;
case "left" :
iLeft -= oContainer.offsetWidth;
break;
case "right" :
default :
iLeft += o.offsetWidth;
}
while (o.offsetParent) { o = o.offsetParent; iLeft += o.offsetLeft; iTop += o.offsetTop; }
oContainer.style.left = iLeft + "px"; oContainer.style.top = iTop + "px"; oContainer.style.visibility = "visible";
},
//菜单设置(菜单对象)
SetMenu: function(menu) {
var oThis = this, index = this._index, oContainer = this.Container[index];
Each(menu, function(o, i){
var oMenu = document.createElement(oThis.Tag);
oMenu.innerHTML = o.txt;
oMenu.onmouseover = function(){
clearTimeout(oThis._timerMenu);
//重新设置菜单
oThis._timerMenu = setTimeout(function(){
oContainer.index = i; oThis._onmenu = oMenu; oThis._index = index + 1; oThis.Set();
}, oThis.Delay);
//重新设置样式
//为解决设置延时后样式的问题每次都全部重新设置
Each(oThis.Container, function(o, i){
if(i > index) return;
Each(o.getElementsByTagName(oThis.Tag), function(o){ o.className = oThis.Class; });
if(i == index){
oMenu.className = oThis.onClass;
} else if(o.index >= 0) {
o.getElementsByTagName(oThis.Tag)[o.index].className = oThis.onClass;
} else return;
});
}
oContainer.appendChild(oMenu);
});
},
//隐藏菜单
Hide: function() {
var oThis = this;
//除第一个外隐藏
Each(this.Container, function(o, i){
if(i == 0){
Each(o.getElementsByTagName(oThis.Tag), function(o, i){ o.className = oThis.Class; })
} else { o.style.visibility = "hidden"; }
o.index = -1;
});
//显示select
Each(document.getElementsByTagName("select"), function(o){ o.style.visibility = "visible"; })
},
//添加菜单(一个菜单对象)
Add: function(arrMenu) {
this.Menu[this.Menu.length] = arrMenu; this.Ini();
},
//删除菜单
Delete: function(index) {
if(index < 0 || index >= this.Menu.length) return;
for(var i = index, len = this.Menu.length - 1; i < len; i++){ this.Menu = this.Menu[i + 1]; }
this.Menu.pop(); this.Ini();
}
};
原文出处:http://www.cnblogs.com/cloudgamer/archive/2008/06/28/1231557.html