右键菜单的JS类
来源:百度文库 编辑:神马文学网 时间:2024/05/20 14:47:32
Source:http://www.limboy.com/2006/10/22/contentmenu/右键菜单在web交互设计里并不是很常用的东西,因为普通用户在浏览网页时很少会想到能用右键来操作,就像他们很难习惯拖拽一样,但在某些环境中,拖拽会成为很自然的操作——其实都跟桌面软件的操作习惯有关。所以右键菜单在某些情况下也是很有用的,抓虾的feed列表里就可以使用右键菜单,如果网页里调用了google maps,而且占据了很大的客户端面积,用右键菜单也会更方便。最近做的项目里就要用到这个,我写了一个简单的右键菜单,并且学习把它封装成一个类。
以下是html形式的代码:
菜单的CSS:
#mousemenu{ position:absolute; background:url(leftbg.jpg) no-repeat; } .mousemenumain{ width:100%; float:left; margin:0px 5px 0px 22px; background:url(tempbg.jpg); border:1px solid #999; border-left:none; } *:first-child+html .mousemenumain{margin:0px 5px 0px 11px;} * html .mousemenumain{margin:0px 5px 0px 11px;} .mousemenumain ul{ padding:0px; margin:0px 0px 0px 0px; list-style:none; width:100%; } .mousemenumain ul li{ width:100%; } .mousemenumain ul li a{ display:block; text-decoration:none; color:#000000; margin:0px 0px 0px 0px; height:20px; line-height:20px; overflow-x:hidden; width:200px; } .mousemenumain ul li a:hover{ background:#0000ee; border:0px solid #00ccff; text-decoration:none; color:#fff; cursor:pointer; } .mousemenumain ul li span{ margin:0px 15px; display:block; }
控制菜单弹出位置的JS程序:
document.oncontextmenu = ShowMenu; function ShowMenu(ev){ var obj=document.getElementById('mousemenu'); obj.style.display='none'; ev = ev || window.event; var showplace=GetMousexy(ev); obj.style.top=showplace.y+"px"; obj.style.left=showplace.x+"px"; var menuplaceX=parseInt(obj.style.left)+parseInt(obj.style.width)+document.body.scrollLeft; //获得菜单右边缘的坐标 var j=0; for(var i=0;idocument.body.clientWidth){ //如果菜单右边缘超出浏览器边框,则让菜单出现在鼠标左侧 obj.style.left=(showplace.x-parseInt(obj.style.width)-26)+"px"; } if(menuplaceY>document.documentElement.clientHeight){ //如果菜单下边缘超出浏览器边框,则让菜单出现在鼠标上侧 obj.style.top=(showplace.y-20*j)+"px"; } obj.style.display=''; return false; //阻止原来的右键菜单出现 } function GetMousexy(ev){ //获取鼠标坐标 if(ev.pageX || ev.pageY){ return {x:ev.pageX, y:ev.pageY}; //适用于FIREFOX } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, //适用于IE y:ev.clientY + document.body.scrollTop - document.body.clientTop } }
需要注意的就是不能让菜单超出浏览器边缘,产生滚动条。
最后的效果:点这里
但是这样做的话,就必须把菜单的HTML代码写在网页面文件里,不能随时调用,如果一个页面里会出现多个菜单的话,就要每个都写一套HTML代码。如果用JS来创建菜单,并且把CSS和程序都封装到一个类里面,每次要用菜单的时候就只需要写很少的代码创建一个实例,虽然第一次比较麻烦,但以后就很方便了:
/********************************************** * Name: context menu class * Author: Dexter.Yy (dexter.yy@gmail.com) * Author URI: http://www.limboy.com/ * Version: 2006.10.22 **********************************************/ function RightMenu() { var MainMenu; //主菜单 var InLineUl; var MenuItem; //菜单项 this.MainMenuPosition = "absolute"; this.MainMenuLeftBackground = "url(leftbg.jpg) no-repeat"; //主菜单右边文字 this.MainMenuWidth = "200px"; this.MainMenuHeight = "0px"; this.MainMenuRightBackground = "url(tempbg.jpg)"; //主菜单内容部分的背景 this.createMainMenu(); } RightMenu.prototype.createMainMenu = function() //创建主菜单 { this.InLineUl = document.createElement("ul"); this.InLineUl.style.padding = "0px"; this.InLineUl.style.margin = "0px 0px 0px 0px"; this.InLineUl.style.listStyle = "none"; this.InLineUl.style.width = "100%"; this.InLineUl.id="allitems"; InLineDiv = document.createElement("div"); InLineDiv.style.width = "100%"; //整个菜单的样式 InLineDiv.style.margin = "0px 5px 0px 22px"; InLineDiv.style.background = this.MainMenuRightBackground; InLineDiv.style.border = "2px solid #0033ff"; InLineDiv.style.borderLeft = "none"; InLineDiv.appendChild(this.InLineUl.cloneNode(true)); this.MainMenu = document.createElement("div"); this.MainMenu.style.position = this.MainMenuPosition; this.MainMenu.style.background = this.MainMenuLeftBackground; this.MainMenu.style.width = this.MainMenuWidth; this.MainMenu.appendChild(InLineDiv); this.MainMenu.style.display = "none"; document.body.appendChild(this.MainMenu); } RightMenu.prototype.appendMenuItem = function(MenuItems) //添加菜单项 { if(MenuItems=='')return; if(this.MainMenu.firstChild.firstChild) { this.MainMenuHeight = "0px"; this.MainMenu.firstChild.replaceChild(this.InLineUl.cloneNode(true),this.MainMenu.firstChild.firstChild); } for(var item in MenuItems) { MenuItemSpan = document.createElement("span"); MenuItemSpan.style.margin = "0px 15px"; MenuItemSpan.style.height = "28px"; MenuItemSpan.style.lineHeight = "28px"; MenuItemSpan.style.display = "block"; MenuItemSpan.innerHTML = MenuItems[item][0]; MenuItemSpan.setAttribute("hasmenu",1); MenuItemSpan.oncontextmenu = function(){return false;} MenuItemA = document.createElement("a"); MenuItemA.setAttribute('href',MenuItems[item][2]); MenuItemA.target = MenuItems[item][1]; MenuItemA.onmouseout = function() //每个菜单项的样式 { this.style.background = ""; this.style.display = "block"; this.style.textDecoration = "none"; this.style.color = "#000000"; this.style.margin = "0px 0px 0px 0px"; this.style.width = "200px"; this.style.height = "28px"; this.style.lineHeight = "28px"; this.style.fontSize = "12px"; this.style.overflowX = "hidden"; } MenuItemA.onmouseout(); MenuItemA.onmouseover = function() //鼠标滑过时菜单项的样式 { this.style.background = "#0000ee"; this.style.border = "0px solid #00ccff"; this.style.textDecoration = "none"; this.style.color = "#fff"; this.style.cursor = "pointer"; } MenuItemA.appendChild(MenuItemSpan); MenuItemLi = document.createElement("li"); MenuItemLi.style.width = "100%"; MenuItemLi.appendChild(MenuItemA); this.MainMenuHeight =(parseInt(this.MainMenuHeight)+parseInt(MenuItemSpan.style.height))+"px"; this.MainMenu.firstChild.firstChild.appendChild(MenuItemLi); } } RightMenu.prototype.GetMousexy = function(ev) { if(ev.pageX || ev.pageY) { return {x:ev.pageX, y:ev.pageY}; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop } } RightMenu.prototype.ShowMenu = function(ev,MenuItems) { this.appendMenuItem(MenuItems); this.MainMenu.style.display='none'; ev = ev || window.event; var showplace=this.GetMousexy(ev); this.MainMenu.style.top=showplace.y+"px"; this.MainMenu.style.left=showplace.x+"px"; var menuplaceX=parseInt(this.MainMenu.style.left)+parseInt(this.MainMenu.style.width)+document.body.scrollLeft; if(menuplaceX>document.body.clientWidth) { this.MainMenu.style.left=(showplace.x-parseInt(this.MainMenu.style.width)-26)+"px"; } var menuplaceY=parseInt(this.MainMenu.style.top)+parseInt(this.MainMenuHeight)-document.body.scrollTop; if(menuplaceY>document.documentElement.clientHeight) { this.MainMenu.style.top=(showplace.y-parseInt(this.MainMenuHeight))+"px"; } this.MainMenu.style.display=''; return false; }
调用这个类的方法是……首先创建菜单的对象,在window.onload = function(){}或body onload=”"里加上:
YYmenu = new RightMenu();
注意不能写作var YYmenu = new RightMenu();那样YYmenu就不是全局的了……
接下来,根据实际需要,设置菜单的具体项目,写成一个数组:[”菜单项的名称”,”打开方式”,”点击的事件”],比如:
var b=[ //设置菜单b的具体项目 ["菜单b菜单b1","_blank","javascript:alert('hahahaha')"], ["菜单b菜单b2","","javascript:alert('xixixixi')"], ["菜单b菜单b3","","javascript:alert('xixixixi')"], ["菜单b菜单b4","","javascript:alert('xixixixi')"], ["菜单b菜单b5","","javascript:alert('xixixixi')"], ["菜单b菜单b6","","javascript:alert('xixixixi')"] ];
需要几种样式的菜单,就建立几个数组。然后,给需要右键弹出菜单的页面元素加上oncontextmenu事件和自定义属性“hasmenu”(如果没有覆盖整个页面的全局右键菜单,就不用加这个属性), 比如:
参数“b”就是包含菜单项目的那个数组。
如果想要在整个页面任何地方点右键都可以弹出一个通用的菜单,需要像这些调用:
if (window.ActiveXObject){ document.oncontextmenu=function(yy) //适用于IE { //alert(event.srcElement.nodeName); if (event.srcElement.getAttribute("hasmenu")!="1"){ return YYmenu.ShowMenu(yy,a); } } }else{ document.oncontextmenu=function(event) //适用于FIREFOX { if (event.target.getAttribute("hasmenu")!="1"){ return YYmenu.ShowMenu(event,a); } } }
这里我处理的不太好,IE和FIREFOX在获取鼠标当前目标时,有一些差异还没完全理解……
最后的效果:点这里
这个javascript类的源文件:点这里
菜单的外观我就没时间弄了,如果你想把菜单做成本文左上角那副图里的效果,只要换一张背景图片,并且给每个LI加上背景就行了……
以下是html形式的代码:
菜单的CSS:
#mousemenu{ position:absolute; background:url(leftbg.jpg) no-repeat; } .mousemenumain{ width:100%; float:left; margin:0px 5px 0px 22px; background:url(tempbg.jpg); border:1px solid #999; border-left:none; } *:first-child+html .mousemenumain{margin:0px 5px 0px 11px;} * html .mousemenumain{margin:0px 5px 0px 11px;} .mousemenumain ul{ padding:0px; margin:0px 0px 0px 0px; list-style:none; width:100%; } .mousemenumain ul li{ width:100%; } .mousemenumain ul li a{ display:block; text-decoration:none; color:#000000; margin:0px 0px 0px 0px; height:20px; line-height:20px; overflow-x:hidden; width:200px; } .mousemenumain ul li a:hover{ background:#0000ee; border:0px solid #00ccff; text-decoration:none; color:#fff; cursor:pointer; } .mousemenumain ul li span{ margin:0px 15px; display:block; }
控制菜单弹出位置的JS程序:
document.oncontextmenu = ShowMenu; function ShowMenu(ev){ var obj=document.getElementById('mousemenu'); obj.style.display='none'; ev = ev || window.event; var showplace=GetMousexy(ev); obj.style.top=showplace.y+"px"; obj.style.left=showplace.x+"px"; var menuplaceX=parseInt(obj.style.left)+parseInt(obj.style.width)+document.body.scrollLeft; //获得菜单右边缘的坐标 var j=0; for(var i=0;i
需要注意的就是不能让菜单超出浏览器边缘,产生滚动条。
最后的效果:点这里
但是这样做的话,就必须把菜单的HTML代码写在网页面文件里,不能随时调用,如果一个页面里会出现多个菜单的话,就要每个都写一套HTML代码。如果用JS来创建菜单,并且把CSS和程序都封装到一个类里面,每次要用菜单的时候就只需要写很少的代码创建一个实例,虽然第一次比较麻烦,但以后就很方便了:
/********************************************** * Name: context menu class * Author: Dexter.Yy (dexter.yy@gmail.com) * Author URI: http://www.limboy.com/ * Version: 2006.10.22 **********************************************/ function RightMenu() { var MainMenu; //主菜单 var InLineUl; var MenuItem; //菜单项 this.MainMenuPosition = "absolute"; this.MainMenuLeftBackground = "url(leftbg.jpg) no-repeat"; //主菜单右边文字 this.MainMenuWidth = "200px"; this.MainMenuHeight = "0px"; this.MainMenuRightBackground = "url(tempbg.jpg)"; //主菜单内容部分的背景 this.createMainMenu(); } RightMenu.prototype.createMainMenu = function() //创建主菜单 { this.InLineUl = document.createElement("ul"); this.InLineUl.style.padding = "0px"; this.InLineUl.style.margin = "0px 0px 0px 0px"; this.InLineUl.style.listStyle = "none"; this.InLineUl.style.width = "100%"; this.InLineUl.id="allitems"; InLineDiv = document.createElement("div"); InLineDiv.style.width = "100%"; //整个菜单的样式 InLineDiv.style.margin = "0px 5px 0px 22px"; InLineDiv.style.background = this.MainMenuRightBackground; InLineDiv.style.border = "2px solid #0033ff"; InLineDiv.style.borderLeft = "none"; InLineDiv.appendChild(this.InLineUl.cloneNode(true)); this.MainMenu = document.createElement("div"); this.MainMenu.style.position = this.MainMenuPosition; this.MainMenu.style.background = this.MainMenuLeftBackground; this.MainMenu.style.width = this.MainMenuWidth; this.MainMenu.appendChild(InLineDiv); this.MainMenu.style.display = "none"; document.body.appendChild(this.MainMenu); } RightMenu.prototype.appendMenuItem = function(MenuItems) //添加菜单项 { if(MenuItems=='')return; if(this.MainMenu.firstChild.firstChild) { this.MainMenuHeight = "0px"; this.MainMenu.firstChild.replaceChild(this.InLineUl.cloneNode(true),this.MainMenu.firstChild.firstChild); } for(var item in MenuItems) { MenuItemSpan = document.createElement("span"); MenuItemSpan.style.margin = "0px 15px"; MenuItemSpan.style.height = "28px"; MenuItemSpan.style.lineHeight = "28px"; MenuItemSpan.style.display = "block"; MenuItemSpan.innerHTML = MenuItems[item][0]; MenuItemSpan.setAttribute("hasmenu",1); MenuItemSpan.oncontextmenu = function(){return false;} MenuItemA = document.createElement("a"); MenuItemA.setAttribute('href',MenuItems[item][2]); MenuItemA.target = MenuItems[item][1]; MenuItemA.onmouseout = function() //每个菜单项的样式 { this.style.background = ""; this.style.display = "block"; this.style.textDecoration = "none"; this.style.color = "#000000"; this.style.margin = "0px 0px 0px 0px"; this.style.width = "200px"; this.style.height = "28px"; this.style.lineHeight = "28px"; this.style.fontSize = "12px"; this.style.overflowX = "hidden"; } MenuItemA.onmouseout(); MenuItemA.onmouseover = function() //鼠标滑过时菜单项的样式 { this.style.background = "#0000ee"; this.style.border = "0px solid #00ccff"; this.style.textDecoration = "none"; this.style.color = "#fff"; this.style.cursor = "pointer"; } MenuItemA.appendChild(MenuItemSpan); MenuItemLi = document.createElement("li"); MenuItemLi.style.width = "100%"; MenuItemLi.appendChild(MenuItemA); this.MainMenuHeight =(parseInt(this.MainMenuHeight)+parseInt(MenuItemSpan.style.height))+"px"; this.MainMenu.firstChild.firstChild.appendChild(MenuItemLi); } } RightMenu.prototype.GetMousexy = function(ev) { if(ev.pageX || ev.pageY) { return {x:ev.pageX, y:ev.pageY}; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop } } RightMenu.prototype.ShowMenu = function(ev,MenuItems) { this.appendMenuItem(MenuItems); this.MainMenu.style.display='none'; ev = ev || window.event; var showplace=this.GetMousexy(ev); this.MainMenu.style.top=showplace.y+"px"; this.MainMenu.style.left=showplace.x+"px"; var menuplaceX=parseInt(this.MainMenu.style.left)+parseInt(this.MainMenu.style.width)+document.body.scrollLeft; if(menuplaceX>document.body.clientWidth) { this.MainMenu.style.left=(showplace.x-parseInt(this.MainMenu.style.width)-26)+"px"; } var menuplaceY=parseInt(this.MainMenu.style.top)+parseInt(this.MainMenuHeight)-document.body.scrollTop; if(menuplaceY>document.documentElement.clientHeight) { this.MainMenu.style.top=(showplace.y-parseInt(this.MainMenuHeight))+"px"; } this.MainMenu.style.display=''; return false; }
调用这个类的方法是……首先创建菜单的对象,在window.onload = function(){}或body onload=”"里加上:
YYmenu = new RightMenu();
注意不能写作var YYmenu = new RightMenu();那样YYmenu就不是全局的了……
接下来,根据实际需要,设置菜单的具体项目,写成一个数组:[”菜单项的名称”,”打开方式”,”点击的事件”],比如:
var b=[ //设置菜单b的具体项目 ["菜单b菜单b1","_blank","javascript:alert('hahahaha')"], ["菜单b菜单b2","","javascript:alert('xixixixi')"], ["菜单b菜单b3","","javascript:alert('xixixixi')"], ["菜单b菜单b4","","javascript:alert('xixixixi')"], ["菜单b菜单b5","","javascript:alert('xixixixi')"], ["菜单b菜单b6","","javascript:alert('xixixixi')"] ];
需要几种样式的菜单,就建立几个数组。然后,给需要右键弹出菜单的页面元素加上oncontextmenu事件和自定义属性“hasmenu”(如果没有覆盖整个页面的全局右键菜单,就不用加这个属性), 比如:
这是需要右键弹出菜单的元素
参数“b”就是包含菜单项目的那个数组。
如果想要在整个页面任何地方点右键都可以弹出一个通用的菜单,需要像这些调用:
if (window.ActiveXObject){ document.oncontextmenu=function(yy) //适用于IE { //alert(event.srcElement.nodeName); if (event.srcElement.getAttribute("hasmenu")!="1"){ return YYmenu.ShowMenu(yy,a); } } }else{ document.oncontextmenu=function(event) //适用于FIREFOX { if (event.target.getAttribute("hasmenu")!="1"){ return YYmenu.ShowMenu(event,a); } } }
这里我处理的不太好,IE和FIREFOX在获取鼠标当前目标时,有一些差异还没完全理解……
最后的效果:点这里
这个javascript类的源文件:点这里
菜单的外观我就没时间弄了,如果你想把菜单做成本文左上角那副图里的效果,只要换一张背景图片,并且给每个LI加上背景就行了……