一个右键菜单的JS类

右键菜单在web交互设计里并不是很常用的东西,因为普通用户在浏览网页时很少会想到能用右键来操作,就像他们很难习惯拖拽一样,但在某些环境中,拖拽会成为很自然的操作——其实都跟桌面软件的操作习惯有关。所以右键菜单在某些情况下也是很有用的,抓虾的feed列表里就可以使用右键菜单,如果网页里调用了google maps,而且占据了很大的客户端面积,用右键菜单也会更方便。最近做的项目里就要用到这个,我写了一个简单的右键菜单,并且学习把它封装成一个类。

以下是html形式的代码:

  1. <div id="mousemenu" style="display: none; width: 200px;">
  2. <divclass="mousemenumain">
  3. <ul id="allitems">
  4. <li><ahref=""><span>菜单项目1</span></a></li>
  5. <li><ahref=""><span>菜单项目2</span></a></li>
  6. <li><ahref=""><span>菜单项目3</span></a></li>
  7. <li><ahref=""><span>菜单项目4长度超出长度超出长度超出长度超出长度超出长度超出</span></a></li>
  8. <li><ahref=""><span>菜单项目5</span></a></li>
  9. <li><ahref=""><span>菜单项目6</span></a></li>
  10. <li><ahref=""><span>菜单项目7</span></a></li>
  11. <li><ahref=""><span>菜单项目8</span></a></li>
  12. </ul>
  13. </div>
  14. </div>

菜单的CSS:

  1. #mousemenu{
  2. position:absolute;
  3. background:url(leftbg.jpg) no-repeat;
  4. }
  5. .mousemenumain{
  6. width:100%;
  7. float:left;
  8. margin:0px5px 0px 22px;
  9. background:url(tempbg.jpg);
  10. border:1pxsolid #999;
  11. border-left:none;
  12. }
  13. *:first-child+html.mousemenumain{margin:0px 5px 0px 11px;} * html .mousemenumain{margin:0px 5px 0px 11px;}
  14. .mousemenumainul{
  15. padding:0px;
  16. margin:0px0px 0px 0px;
  17. list-style:none;
  18. width:100%;
  19. }
  20. .mousemenumainul li{
  21. width:100%;
  22. }
  23. .mousemenumainul li a{
  24. display:block;
  25. text-decoration:none;
  26. color:#000000;
  27. margin:0px0px 0px 0px;
  28. height:20px;
  29. line-height:20px;
  30. overflow-x:hidden;
  31. width:200px;
  32. }
  33. .mousemenumainul li a:hover{
  34. background:#0000ee;
  35. border:0pxsolid #00ccff;
  36. text-decoration:none;
  37. color:#fff;
  38. cursor:pointer;
  39. }
  40. .mousemenumainul li span{
  41. margin:0px15px;
  42. display:block;
  43. }

控制菜单弹出位置的JS程序:

  1. document.oncontextmenu = ShowMenu;
  2. functionShowMenu(ev){
  3. var obj=document.getElementById('mousemenu');
  4. obj.style.display='none';
  5. ev = ev || window.event;
  6. var showplace=GetMousexy(ev);
  7. obj.style.top=showplace.y+"px";
  8. obj.style.left=showplace.x+"px";
  9. var menuplaceX=parseInt(obj.style.left)+parseInt(obj.style.width)+document.body.scrollLeft; //获得菜单右边缘的坐标
  10. var j=0;
  11. for(var i=0;i<document.getElementById('allitems').childNodes.length;i++){ //获得菜单项的数量
  12. if(document.getElementById('allitems').childNodes.item(i).tagName=="LI"){j++;}
  13. }
  14. var menuplaceY=parseInt(obj.style.top)+20*j-document.body.scrollTop; //获得菜单下边缘的坐标
  15. if(menuplaceX>document.body.clientWidth){ //如果菜单右边缘超出浏览器边框,则让菜单出现在鼠标左侧
  16. obj.style.left=(showplace.x-parseInt(obj.style.width)-26)+"px";
  17. }
  18. if(menuplaceY>document.documentElement.clientHeight){ //如果菜单下边缘超出浏览器边框,则让菜单出现在鼠标上侧
  19. obj.style.top=(showplace.y-20*j)+"px";
  20. }
  21. obj.style.display='';
  22. return false; //阻止原来的右键菜单出现
  23. }
  24. functionGetMousexy(ev){ //获取鼠标坐标
  25. if(ev.pageX || ev.pageY){
  26. return{x:ev.pageX, y:ev.pageY}; //适用于FIREFOX
  27. }return {
  28. x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, //适用于IE
  29. y:ev.clientY + document.body.scrollTop - document.body.clientTop
  30. }
  31. }

需要注意的就是不能让菜单超出浏览器边缘,产生滚动条。

最后的效果:点这里

但是这样做的话,就必须把菜单的HTML代码写在网页面文件里,不能随时调用,如果一个页面里会出现多个菜单的话,就要每个都写一套HTML代码。 如果用JS来创建菜单,并且把CSS和程序都封装到一个类里面,每次要用菜单的时候就只需要写很少的代码创建一个实例,虽然第一次比较麻烦,但以后就很方 便了:

  1. /**********************************************
  2. * Name: context menu class
  3. * Author: Dexter.Yy (dexter.yy@gmail.com)
  4. * Author URI: http://www.limboy.com/
  5. * Version: 2006.10.22
  6. **********************************************/
  7. functionRightMenu()
  8. {
  9. varMainMenu; //主菜单
  10. varInLineUl;
  11. varMenuItem; //菜单项
  12. this.MainMenuPosition = "absolute";
  13. this.MainMenuLeftBackground = "url(leftbg.jpg) no-repeat"; //主菜单右边文字
  14. this.MainMenuWidth = "200px";
  15. this.MainMenuHeight = "0px";
  16. this.MainMenuRightBackground = "url(tempbg.jpg)"; //主菜单内容部分的背景
  17. this.createMainMenu();
  18. }
  19. RightMenu.prototype.createMainMenu = function() //创建主菜单
  20. {
  21. this.InLineUl = document.createElement("ul");
  22. this.InLineUl.style.padding = "0px";
  23. this.InLineUl.style.margin = "0px 0px 0px 0px";
  24. this.InLineUl.style.listStyle = "none";
  25. this.InLineUl.style.width = "100%";
  26. this.InLineUl.id="allitems";
  27. InLineDiv = document.createElement("div");
  28. InLineDiv.style.width = "100%"; //整个菜单的样式
  29. InLineDiv.style.margin = "0px 5px 0px 22px";
  30. InLineDiv.style.background = this.MainMenuRightBackground;
  31. InLineDiv.style.border = "2px solid #0033ff";
  32. InLineDiv.style.borderLeft = "none";
  33. InLineDiv.appendChild(this.InLineUl.cloneNode(true));
  34. this.MainMenu = document.createElement("div");
  35. this.MainMenu.style.position = this.MainMenuPosition;
  36. this.MainMenu.style.background = this.MainMenuLeftBackground;
  37. this.MainMenu.style.width = this.MainMenuWidth;
  38. this.MainMenu.appendChild(InLineDiv);
  39. this.MainMenu.style.display = "none";
  40. document.body.appendChild(this.MainMenu);
  41. }
  42. RightMenu.prototype.appendMenuItem = function(MenuItems) //添加菜单项
  43. {
  44. if(MenuItems=='')return;
  45. if(this.MainMenu.firstChild.firstChild)
  46. {
  47. this.MainMenuHeight = "0px";
  48. this.MainMenu.firstChild.replaceChild(this.InLineUl.cloneNode(true),this.MainMenu.firstChild.firstChild);
  49. }
  50. for(varitem in MenuItems)
  51. {
  52. MenuItemSpan = document.createElement("span");
  53. MenuItemSpan.style.margin = "0px 15px";
  54. MenuItemSpan.style.height = "28px";
  55. MenuItemSpan.style.lineHeight = "28px";
  56. MenuItemSpan.style.display = "block";
  57. MenuItemSpan.innerHTML = MenuItems[item][0];
  58. MenuItemSpan.setAttribute("hasmenu",1);
  59. MenuItemSpan.oncontextmenu = function(){return false;}
  60. MenuItemA = document.createElement("a");
  61. MenuItemA.setAttribute('href',MenuItems[item][2]);
  62. MenuItemA.target = MenuItems[item][1];
  63. MenuItemA.onmouseout = function() //每个菜单项的样式
  64. {
  65. this.style.background = "";
  66. this.style.display = "block";
  67. this.style.textDecoration = "none";
  68. this.style.color = "#000000";
  69. this.style.margin = "0px 0px 0px 0px";
  70. this.style.width = "200px";
  71. this.style.height = "28px";
  72. this.style.lineHeight = "28px";
  73. this.style.fontSize = "12px";
  74. this.style.overflowX = "hidden";
  75. }
  76. MenuItemA.onmouseout();
  77. MenuItemA.onmouseover = function() //鼠标滑过时菜单项的样式
  78. {
  79. this.style.background = "#0000ee";
  80. this.style.border = "0px solid #00ccff";
  81. this.style.textDecoration = "none";
  82. this.style.color = "#fff";
  83. this.style.cursor = "pointer";
  84. }
  85. MenuItemA.appendChild(MenuItemSpan);
  86. MenuItemLi = document.createElement("li");
  87. MenuItemLi.style.width = "100%";
  88. MenuItemLi.appendChild(MenuItemA);
  89. this.MainMenuHeight =(parseInt(this.MainMenuHeight)+parseInt(MenuItemSpan.style.height))+"px";
  90. this.MainMenu.firstChild.firstChild.appendChild(MenuItemLi);
  91. }
  92. }
  93. RightMenu.prototype.GetMousexy = function(ev)
  94. {
  95. if(ev.pageX || ev.pageY)
  96. {
  97. return{x:ev.pageX, y:ev.pageY};
  98. }
  99. return{
  100. x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
  101. y:ev.clientY + document.body.scrollTop - document.body.clientTop
  102. }
  103. }
  104. RightMenu.prototype.ShowMenu = function(ev,MenuItems)
  105. {
  106. this.appendMenuItem(MenuItems);
  107. this.MainMenu.style.display='none';
  108. ev = ev || window.event;
  109. varshowplace=this.GetMousexy(ev);
  110. this.MainMenu.style.top=showplace.y+"px";
  111. this.MainMenu.style.left=showplace.x+"px";
  112. varmenuplaceX=parseInt(this.MainMenu.style.left)+parseInt(this.MainMenu.style.width)+document.body.scrollLeft;
  113. if(menuplaceX>document.body.clientWidth)
  114. {
  115. this.MainMenu.style.left=(showplace.x-parseInt(this.MainMenu.style.width)-26)+"px";
  116. }
  117. varmenuplaceY=parseInt(this.MainMenu.style.top)+parseInt(this.MainMenuHeight)-document.body.scrollTop;
  118. if(menuplaceY>document.documentElement.clientHeight)
  119. {
  120. this.MainMenu.style.top=(showplace.y-parseInt(this.MainMenuHeight))+"px";
  121. }
  122. this.MainMenu.style.display='';
  123. returnfalse;
  124. }

调用这个类的方法是……首先创建菜单的对象,在window.onload = function(){}或body onload=”"里加上:

  1. YYmenu = new RightMenu();

注意不能写作var YYmenu = new RightMenu();那样YYmenu就不是全局的了……

接下来,根据实际需要,设置菜单的具体项目,写成一个数组:[”菜单项的名称”,”打开方式”,”点击的事件”],比如:

  1. var b=[ //设置菜单b的具体项目
  2. ["菜单b菜单b1","_blank","javascript:alert('hahahaha')"],
  3. ["菜单b菜单b2","","javascript:alert('xixixixi')"],
  4. ["菜单b菜单b3","","javascript:alert('xixixixi')"],
  5. ["菜单b菜单b4","","javascript:alert('xixixixi')"],
  6. ["菜单b菜单b5","","javascript:alert('xixixixi')"],
  7. ["菜单b菜单b6","","javascript:alert('xixixixi')"]
  8. ];

需要几种样式的菜单,就建立几个数组。然后,给需要右键弹出菜单的页面元素加上oncontextmenu事件和自定义属性“hasmenu”(如果没有覆盖整个页面的全局右键菜单,就不用加这个属性), 比如:

  1. <div oncontextmenu="return YYmenu.ShowMenu(event,b)" hasmenu="1">这是需要右键弹出菜单的元素</div>

参数“b”就是包含菜单项目的那个数组。

如果想要在整个页面任何地方点右键都可以弹出一个通用的菜单,需要像这些调用:

  1. if (window.ActiveXObject){
  2. document.oncontextmenu=function(yy) //适用于IE
  3. { //alert(event.srcElement.nodeName);
  4. if(event.srcElement.getAttribute("hasmenu")!="1"){
  5. returnYYmenu.ShowMenu(yy,a);
  6. }
  7. }
  8. }else{
  9. document.oncontextmenu=function(event) //适用于FIREFOX
  10. {
  11. if(event.target.getAttribute("hasmenu")!="1"){
  12. returnYYmenu.ShowMenu(event,a);
  13. }
  14. }
  15. }

这里我处理的不太好,IE和FIREFOX在获取鼠标当前目标时,有一些差异还没完全理解……

最后的效果:点这里

这个javascript类的源文件:点这里

菜单的外观我就没时间弄了,如果你想把菜单做成本文左上角那副图里的效果,只要换一张背景图片,并且给每个LI加上背景就行了……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值