javascript 右键菜单 支持多级菜单 支持不同节点展示不同菜单 兼容firefox和IE

来源:互联网 发布:超算中心怎么收费 知乎 编辑:程序博客网 时间:2024/05/19 22:07

手头上的项目需要实现javascript右键菜单功能,并支持不同节点显示不同的菜单,后期还要根据权限来控制菜单的显示项,这里先写一下如果实现标题所说的功能:

说明:参考了一些文章,自己再重构优化。

首先是一个hmtl文件,在里面定义了两个菜单rightMenu1和rightMenu2,并导入rightMenu.css和rightMenu.js,如下所示:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>自定义多级右键菜单</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><link href="rightMenu.css" rel="stylesheet" type="text/css"><script type="text/javascript" src="rightMenu.js"></script></head><body><div id="12345" oncontextmenu="(function(event){setRightMenu(event,'rightMenu1');})(event);return false;" style="width:150px;height:20px;background:#E8FFE8;border:2px solid #336699;">第一个右键菜单</div></br><div id="56789" oncontextmenu="(function(event){setRightMenu(event,'rightMenu2');})(event);return false;" style="width:150px;height:20px;background:#E8FFE8;border:2px solid #336699;">第二个右键菜单</div><div class="rightMenu"  id="rightMenu1" style="display:none">    <ul>        <li onclick="window.open('http://www.baidu.com')">打开百度</li><li>我有二级菜单        <ul>        <li>111</li>        <li>222</li>        <li>333</li>        </ul>        </li>    </ul></div><div class="rightMenu"  id="rightMenu2" style="display:none">    <ul>        <li onclick="window.open('http://www.csdn.com')">打开CSDN</li>        <li>我有二级菜单        <ul>        <li>111</li>        <li>222</li>        <li>文件        <ul>        <li>新建jsp文件</li>        <li>新建java文件</li>        </ul>        </li>        </ul>        </li></ul></div></body></html>

接下来是rightMenu.js:

/** * 右键菜单功能,要使用右键功能时,在所在元素的标签中添加这样的配置: *  oncontextmenu="(function(event){setRightMenu(event,'rightMenuId');})(event);return false;"  *   其中rightMenuId是指已经定义好的右键菜单的ID。 *  注意: *  1、需要用到直线和箭头两个图片,在该Demo的images目录下可以找到 *  2、如要使用该Demo的菜单样式,div的class属性请设置为rightMenu,并在页面导入rightMenu.css *  3、程序支持多级菜单,所以定义菜单时请使用div+ul标签进行定义:最外层用div,菜单内容用ul+li标签,如: *  <div class="rightMenu"  id="rightMenu1" style="display:none">    <ul>        <li>菜单项1</li>        <li>            菜单项2,我有多级标签            <ul>                <li>111</li>                <li>222</li>                <li>333</li>            </ul>        </li>    </ul> <div>       * 林树涛 * 2011年11月17日14:34:54 * *///当前显示的右键菜单的IDvar currentRightMenuID;//隐藏当前显示的右键菜单function hideRightMenu(){if(document.getElementById(currentRightMenuID)){document.getElementById(currentRightMenuID).style.display = "none";}}//点击页面其他地方时隐藏菜单  document.onclick = function (){  hideRightMenu();};   /* * 设置(配置)右键菜单,并弹出右键菜单 * rightMenuId:右键菜单的ID * */function setRightMenu(event,rightMenuId){var event = event || window.event;hideRightMenu();currentRightMenuID = rightMenuId;var oMenu = document.getElementById(rightMenuId);var aUl = oMenu.getElementsByTagName("ul");var aLi = oMenu.getElementsByTagName("li");var showTimer = hideTimer = null;var i = 0;var maxWidth = maxHeight = 0;var aDoc = [document.documentElement.offsetWidth, document.documentElement.offsetHeight];var getOffset = {top: function (obj) {return obj.offsetTop + (obj.offsetParent ? arguments.callee(obj.offsetParent) : 0) },left: function (obj) {return obj.offsetLeft + (obj.offsetParent ? arguments.callee(obj.offsetParent) : 0) }};oMenu.style.display = "none";for (i = 0; i < aLi.length; i++){//为含有子菜单的li加上箭头aLi[i].getElementsByTagName("ul")[0] && (aLi[i].className = "sub");//鼠标移入aLi[i].onmouseover = function (){var oThis = this;var oUl = oThis.getElementsByTagName("ul");//鼠标移入样式oThis.className += " active";//显示子菜单if (oUl[0]){clearTimeout(hideTimer);showTimer = setTimeout(function (){for (i = 0; i < oThis.parentNode.children.length; i++){oThis.parentNode.children[i].getElementsByTagName("ul")[0] &&(oThis.parentNode.children[i].getElementsByTagName("ul")[0].style.display = "none");}oUl[0].style.display = "block";/* * offsetHeight/Width、offsetTop/offsetLeft * 等返回的都是只读的并且以数字的形式返回像素值(例如,返回12,而不是'12px')。 * */oUl[0].style.top = oThis.offsetTop + "px";oUl[0].style.left = oThis.offsetWidth + "px";setWidth(oUl[0]);//最大显示范围maxWidth = aDoc[0] - oUl[0].offsetWidth;maxHeight = aDoc[1] - oUl[0].offsetHeight;//防止溢出maxWidth < getOffset.left(oUl[0]) && (oUl[0].style.left = -oUl[0].clientWidth + "px");maxHeight < getOffset.top(oUl[0]) && (oUl[0].style.top = -oUl[0].clientHeight + oThis.offsetTop + oThis.clientHeight + "px")},300);}};//鼠标移出aLi[i].onmouseout = function (){var oThis = this;var oUl = oThis.getElementsByTagName("ul");//鼠标移出样式oThis.className = oThis.className.replace(/\s?active/,"");clearTimeout(showTimer);hideTimer = setTimeout(function (){for (i = 0; i < oThis.parentNode.children.length; i++){oThis.parentNode.children[i].getElementsByTagName("ul")[0] &&(oThis.parentNode.children[i].getElementsByTagName("ul")[0].style.display = "none");}},300);};}  oMenu.style.display = "block"; oMenu.style.top = event.clientY + "px"; oMenu.style.left = event.clientX + "px";/*setWidth(aUl[0]);//最大显示范围maxWidth = aDoc[0] - oMenu.offsetWidth;maxHeight = aDoc[1] - oMenu.offsetHeight;//防止菜单溢出oMenu.offsetTop > maxHeight && (oMenu.style.top = maxHeight + "px");oMenu.offsetLeft > maxWidth && (oMenu.style.left = maxWidth + "px");*/return false;}//##########end of setRightMenu//取li中最大的宽度, 并赋给同级所有lifunction setWidth(obj){maxWidth = 0;for (i = 0; i < obj.children.length; i++){var oLi = obj.children[i];var iWidth = oLi.clientWidth - parseInt(oLi.currentStyle ? oLi.currentStyle["paddingLeft"] : getComputedStyle(oLi,null)["paddingLeft"]) * 2if (iWidth > maxWidth) maxWidth = iWidth;}for (i = 0; i < obj.children.length; i++){obj.children[i].style.width = maxWidth + "px";} } 

接下来时样式文件:rightMenu.css:

@CHARSET "UTF-8";/* 鼠标右键样式文件 2011年11月17日15:28:47 * */.rightMenu{position:absolute;top:-9999px;left:-9999px;font:12px/1.5 \5fae\8f6f\96c5\9ed1;}.rightMenu ul{list-style-type:none;float:left;border:1px solid #979797;background:#f1f1f1 url(images/rightMenu_line.png) 24px 0 repeat-y;padding:2px;box-shadow:2px 2px 2px rgba(0,0,0,.6);}.rightMenu ul li{float:left;clear:both;height:24px;cursor:pointer;line-height:24px;white-space:nowrap;padding:0 30px;}.rightMenu ul li.sub{background-repeat:no-repeat;background-position:right 9px;background-image:url(images/rightMenu_arrow.png);}.rightMenu ul li.active{background-color:#f1f3f6;border-radius:3px;border:1px solid #aecff7;height:22px;line-height:22px;background-position:right -8px;padding:0 29px;}.rightMenu ul ul{display:none;position:absolute;}

效果图如下:


第二个菜单:


用到的来个素材,小三角和直线:


直线:


就是一小点,为了看得清楚摆了好多个,呵呵。