共享社区互联网资源共享社区网页资料共享 JavaScript 自定义多级联动浮动菜单

   
1  /  1  页   1 跳转 查看:1248

JavaScript 自定义多级联动浮动菜单

JavaScript 自定义多级联动浮动菜单

特点:
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
金鳞岂是池中物,一遇风云便化龙
 

回复:JavaScript 自定义多级联动浮动菜单

是不是真的啊








无极魔道
 
1  /  1  页   1 跳转

版权所有 老猫的理想   Sitemap

Powered by Discuz!NT 2.1.202    Copyright © 2001-2009 Comsenz Inc.
Processed in 0.03125 second(s) , 4 queries. 冀ICP备05001409号
返顶部