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

来源:互联网 发布:成都卧龙大数据创始人 编辑:程序博客网 时间:2024/05/20 00:17

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

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

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

[html] view plaincopy
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <title>自定义多级右键菜单</title>  
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  6. <link href="rightMenu.css" rel="stylesheet" type="text/css">  
  7. <script type="text/javascript" src="rightMenu.js"></script>  
  8. </head>  
  9. <body>  
  10. <div id="12345" oncontextmenu="(function(event){setRightMenu(event,'rightMenu1');})(event);return false;"   
  11. style="width:150px;height:20px;background:#E8FFE8;border:2px solid #336699;">  
  12. 第一个右键菜单  
  13. </div></br>  
  14. <div id="56789" oncontextmenu="(function(event){setRightMenu(event,'rightMenu2');})(event);return false;"   
  15. style="width:150px;height:20px;background:#E8FFE8;border:2px solid #336699;">  
  16. 第二个右键菜单  
  17. </div>  
  18.   
  19. <div class="rightMenu"  id="rightMenu1" style="display:none">  
  20.     <ul>  
  21.         <li onclick="window.open('http://www.baidu.com')">打开百度</li>  
  22.         <li>我有二级菜单  
  23.             <ul>  
  24.                 <li>111</li>  
  25.                 <li>222</li>  
  26.                 <li>333</li>  
  27.             </ul>  
  28.         </li>  
  29.     </ul>  
  30. </div>  
  31.   
  32. <div class="rightMenu"  id="rightMenu2" style="display:none">  
  33.     <ul>  
  34.         <li onclick="window.open('http://www.csdn.com')">打开CSDN</li>  
  35.         <li>我有二级菜单  
  36.             <ul>  
  37.                 <li>111</li>  
  38.                 <li>222</li>  
  39.                 <li>文件  
  40.                     <ul>  
  41.                         <li>新建jsp文件</li>  
  42.                         <li>新建java文件</li>  
  43.                     </ul>  
  44.                 </li>  
  45.             </ul>  
  46.         </li>  
  47.     </ul>  
  48. </div>  
  49. </body>  
  50. </html>  

接下来是rightMenu.js:
[javascript] view plaincopy
  1. /** 
  2.  * 右键菜单功能,要使用右键功能时,在所在元素的标签中添加这样的配置: 
  3.  *  oncontextmenu="(function(event){setRightMenu(event,'rightMenuId');})(event);return false;"  
  4.  *   其中rightMenuId是指已经定义好的右键菜单的ID。 
  5.  *  注意: 
  6.  *  1、需要用到直线和箭头两个图片,在该Demo的images目录下可以找到 
  7.  *  2、如要使用该Demo的菜单样式,div的class属性请设置为rightMenu,并在页面导入rightMenu.css 
  8.  *  3、程序支持多级菜单,所以定义菜单时请使用div+ul标签进行定义:最外层用div,菜单内容用ul+li标签,如: 
  9.  *  <div class="rightMenu"  id="rightMenu1" style="display:none"> 
  10.         <ul> 
  11.             <li>菜单项1</li> 
  12.             <li> 
  13.                 菜单项2,我有多级标签 
  14.                 <ul> 
  15.                     <li>111</li> 
  16.                     <li>222</li> 
  17.                     <li>333</li> 
  18.                 </ul> 
  19.             </li> 
  20.         </ul> 
  21.      <div>       
  22.  * 林树涛 
  23.  * 2011年11月17日14:34:54 
  24.  * */  
  25.   
  26. //当前显示的右键菜单的ID  
  27. var currentRightMenuID;  
  28.   
  29. //隐藏当前显示的右键菜单  
  30. function hideRightMenu(){  
  31.     if(document.getElementById(currentRightMenuID)){  
  32.         document.getElementById(currentRightMenuID).style.display = "none";  
  33.     }  
  34. }  
  35. //点击页面其他地方时隐藏菜单  
  36.     document.onclick = function (){  
  37.         hideRightMenu();  
  38.     };      
  39.   
  40. /* 
  41.  * 设置(配置)右键菜单,并弹出右键菜单 
  42.  * rightMenuId:右键菜单的ID 
  43.  * */  
  44. function setRightMenu(event,rightMenuId){  
  45.     var event = event || window.event;  
  46.     hideRightMenu();  
  47.     currentRightMenuID = rightMenuId;  
  48.     var oMenu = document.getElementById(rightMenuId);  
  49.     var aUl = oMenu.getElementsByTagName("ul");  
  50.     var aLi = oMenu.getElementsByTagName("li");  
  51.     var showTimer = hideTimer = null;  
  52.     var i = 0;  
  53.     var maxWidth = maxHeight = 0;  
  54.     var aDoc = [document.documentElement.offsetWidth, document.documentElement.offsetHeight];     
  55.     var getOffset = {  
  56.             top: function (obj) {  
  57.                 return obj.offsetTop + (obj.offsetParent ? arguments.callee(obj.offsetParent) : 0)   
  58.             },  
  59.             left: function (obj) {  
  60.                 return obj.offsetLeft + (obj.offsetParent ? arguments.callee(obj.offsetParent) : 0)   
  61.             }     
  62.         };    
  63.     oMenu.style.display = "none";     
  64.     for (i = 0; i < aLi.length; i++){  
  65.         //为含有子菜单的li加上箭头  
  66.         aLi[i].getElementsByTagName("ul")[0] && (aLi[i].className = "sub");  
  67.         //鼠标移入  
  68.         aLi[i].onmouseover = function (){  
  69.             var oThis = this;  
  70.             var oUl = oThis.getElementsByTagName("ul");  
  71.               
  72.             //鼠标移入样式  
  73.             oThis.className += " active";                         
  74.             //显示子菜单  
  75.             if (oUl[0]){  
  76.                 clearTimeout(hideTimer);                  
  77.                 showTimer = setTimeout(function (){  
  78.                     for (i = 0; i < oThis.parentNode.children.length; i++){  
  79.                         oThis.parentNode.children[i].getElementsByTagName("ul")[0] &&  
  80.                         (oThis.parentNode.children[i].getElementsByTagName("ul")[0].style.display = "none");  
  81.                     }  
  82.                     oUl[0].style.display = "block";  
  83.                     /* 
  84.                      * offsetHeight/Width、offsetTop/offsetLeft 
  85.                      * 等返回的都是只读的并且以数字的形式返回像素值(例如,返回12,而不是'12px')。 
  86.                      * */  
  87.                     oUl[0].style.top = oThis.offsetTop + "px";  
  88.                     oUl[0].style.left = oThis.offsetWidth + "px";  
  89.                     setWidth(oUl[0]);                     
  90.                     //最大显示范围                      
  91.                     maxWidth = aDoc[0] - oUl[0].offsetWidth;  
  92.                     maxHeight = aDoc[1] - oUl[0].offsetHeight;                    
  93.                     //防止溢出  
  94.                     maxWidth < getOffset.left(oUl[0]) && (oUl[0].style.left = -oUl[0].clientWidth + "px");  
  95.                     maxHeight < getOffset.top(oUl[0]) && (oUl[0].style.top = -oUl[0].clientHeight + oThis.offsetTop + oThis.clientHeight + "px")  
  96.                 },300);  
  97.             }             
  98.         };  
  99.               
  100.         //鼠标移出    
  101.         aLi[i].onmouseout = function (){  
  102.             var oThis = this;  
  103.             var oUl = oThis.getElementsByTagName("ul");  
  104.             //鼠标移出样式  
  105.             oThis.className = oThis.className.replace(/\s?active/,"");        
  106.             clearTimeout(showTimer);  
  107.             hideTimer = setTimeout(function (){  
  108.                 for (i = 0; i < oThis.parentNode.children.length; i++){  
  109.                     oThis.parentNode.children[i].getElementsByTagName("ul")[0] &&  
  110.                     (oThis.parentNode.children[i].getElementsByTagName("ul")[0].style.display = "none");  
  111.                 }  
  112.             },300);  
  113.         };  
  114.     }  
  115.       
  116.     oMenu.style.display = "block";  
  117.     oMenu.style.top = event.clientY + "px";  
  118.     oMenu.style.left = event.clientX + "px";  
  119. /*  setWidth(aUl[0]); 
  120.     //最大显示范围 
  121.     maxWidth = aDoc[0] - oMenu.offsetWidth; 
  122.     maxHeight = aDoc[1] - oMenu.offsetHeight;    
  123.     //防止菜单溢出 
  124.     oMenu.offsetTop > maxHeight && (oMenu.style.top = maxHeight + "px"); 
  125.     oMenu.offsetLeft > maxWidth && (oMenu.style.left = maxWidth + "px");*/  
  126.     return false;  
  127. }//##########end of setRightMenu  
  128.   
  129.   
  130. //取li中最大的宽度, 并赋给同级所有li    
  131. function setWidth(obj){  
  132.     maxWidth = 0;  
  133.     for (i = 0; i < obj.children.length; i++){  
  134.         var oLi = obj.children[i];            
  135.         var iWidth = oLi.clientWidth - parseInt(oLi.currentStyle ? oLi.currentStyle["paddingLeft"] : getComputedStyle(oLi,null)["paddingLeft"]) * 2  
  136.         if (iWidth > maxWidth) maxWidth = iWidth;  
  137.     }  
  138.     for (i = 0; i < obj.children.length; i++){  
  139.         obj.children[i].style.width = maxWidth + "px";  
  140.     }   
  141. }   

接下来时样式文件:rightMenu.css:
[css] view plaincopy
  1. @CHARSET "UTF-8";  
  2. /* 
  3.  鼠标右键样式文件 
  4.  2011年11月17日15:28:47 
  5.  * */  
  6.   
  7. .rightMenu{  
  8.     position:absolute;  
  9.     top:-9999px;  
  10.     left:-9999px;  
  11.     font:12px/1.5 \5fae\8f6f\96c5\9ed1;  
  12. }  
  13. .rightMenu ul{  
  14.     list-style-type:none;  
  15.     float:left;  
  16.     border:1px solid #979797;  
  17.     background:#f1f1f1 url(images/rightMenu_line.png) 24px 0 repeat-y;  
  18.     padding:2px;  
  19.     box-shadow:2px 2px 2px rgba(0,0,0,.6);  
  20. }  
  21.   
  22. .rightMenu ul li{  
  23.     float:left;  
  24.     clear:both;  
  25.     height:24px;  
  26.     cursor:pointer;  
  27.     line-height:24px;  
  28.     white-space:nowrap;  
  29.     padding:0 30px;  
  30. }  
  31.   
  32. .rightMenu ul li.sub{  
  33.     background-repeat:no-repeat;  
  34.     background-position:right 9px;  
  35.     background-image:url(images/rightMenu_arrow.png);  
  36. }  
  37.   
  38. .rightMenu ul li.active{  
  39.     background-color:#f1f3f6;  
  40.     border-radius:3px;  
  41.     border:1px solid #aecff7;  
  42.     height:22px;  
  43.     line-height:22px;  
  44.     background-position:right -8px;  
  45.     padding:0 29px;  
  46. }  
  47.   
  48. .rightMenu ul ul{  
  49.     display:none;  
  50.     position:absolute;  
  51. }  

效果图如下:


第二个菜单:


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


直线:


就是一小点,为了看得清楚摆了好多个,呵呵
原创粉丝点击