右鍵菜單的設定主要是通過contextmenu事件來激活,由於contextmenu事件是冒泡的,所以可以為document來指定事件,進行頁面中該事件的統一處理。同時,因為contextmenu是一個鼠標事件,所以在event中包含有鼠標位置等一系列信息,可以通過這個來實現對瀏覽器右鍵菜單的模擬。
為了兼容現在的主流瀏覽器,所以先做一個通用的事件加載函數:
1 function eventHandler(dom,type,fn){ 2 if(typeof dom.addEventListener != 'undefined'){ 3 dom.addEventListener(type,fn,false); 4 }else if(typeof dom.attachEvent != 'undefined'){ 5 dom.attachEvent('on'+type,fn); 6 }else{ 7 dom['on'+type] = fn; 8 } 9 }
這個函數首先檢測是否有addEventListener,有的話就用這個,然后是attachEvent,因為IE中都是用這個來加載監聽事件的,特別注意的是事件名前面要加上on,最后如果都不支持的話,就用最原始的方法添加事件。這個事件函數都是在冒泡階段執行的,主要是考慮到IE和一些瀏覽器的早期版本對捕獲的支持不佳,為了統一效果,就全部放在了冒泡階段。
接下來做一個能夠檢測的頁面,主要是檢測事件運行是否正常,特別是滾動以后右鍵菜單的位置
<html> <head> <style type="text/css"> div{ margin-top:50px; margin-bottom: 50px; } </style> <script type="text/javascript"> function eventHandler(dom,type,fn){ if(typeof dom.addEventListener != 'undefined'){ dom.addEventListener(type,fn,false); }else if(typeof dom.attachEvent != 'undefined'){ dom.attachEvent('on'+type,fn); }else{ dom['on'+type] = fn; } } </script> </head> <body> <ul id='myContextMenu' style="padding:0;margin:0;list-style:none;position:absolute;visibility:hidden;background-color:silver;"> <li>hi</li> <li><a href="#">hello</a></li> </ul> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> <div>asdfasf</div> </body> </html>
這樣就完成了一個足夠長的頁面,同時做了右鍵菜單的element,就是那個myContextMenu。接下來就是對contextmenu的設定了。
1 window.onload = function(){ 2 eventHandler(document,'contextmenu',function(event){ 3 event = event || window.event; 4 event.preventDefault?event.preventDefault():(event.returnValue = false); 5 }); 6 }
首先是取消原有的默認右鍵事件。考慮到跨瀏覽器的兼容,就要考慮到IE下是用event.returnValue來取消的,所以寫了個語句專門取消這個默認事件。
接下來就是鼠標的位置了,在其余瀏覽器中,event下pageX和pageY中就保存了鼠標的位置信息,而且是相對於頁面來說的,而不是以窗口client作為參考位置的,可以直接使用來設定右鍵菜單的位置,但是在IE中,部分版本是不支持pageX和pageY的,就需要用clientX和clientY再加滾動的距離來計算鼠標的位置
1 var menu = document.getElementById('myContextMenu'), 2 pageX = event.pageX?event.pageX:(event.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft)), 3 pageY = event.pageY?event.pageY:(event.clientY+(document.body.scrollTop||document.documentElement.scrollTop));
在混雜模式下用document.body,在標准模式下用document.documentElement。再加一下style設置就可以完成對右鍵菜單的設置了。
1 window.onload = function(){ 2 eventHandler(document,'contextmenu',function(event){ 3 event = event || window.event; 4 event.preventDefault?(event.preventDefault()):(event.returnValue = false); 5 var menu = document.getElementById('myContextMenu'), 6 pageX = event.pageX?event.pageX:(event.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft)), 7 pageY = event.pageY?event.pageY:(event.clientY+(document.body.scrollTop||document.documentElement.scrollTop)); 8 menu.style.left = pageX+'px'; 9 menu.style.top = pageY+'px'; 10 menu.style.visibility = 'visible'; 11 }); 12 }
接下來還有一個問題,就是要模擬瀏覽器的右鍵菜單,那么必須在點擊其它地方后隱藏右鍵菜單,這個只要在document上加一個click事件就可以了
1 eventHandler(document,'click',function(event){ 2 document.getElementById('myContextMenu').style.visibility = 'hidden'; 3 })
click事件觸發后,冒泡到document上,用來取消右鍵菜單的顯示,同時也不會影響到其余click事件的處理。
最后所以的代碼集合一下:

1 <html> 2 <head> 3 <style type="text/css"> 4 div{ 5 margin-top:50px; 6 margin-bottom: 50px; 7 } 8 </style> 9 <script type="text/javascript"> 10 window.onload = function(){ 11 eventHandler(document,'contextmenu',function(event){ 12 event = event || window.event; 13 event.preventDefault?(event.preventDefault()):(event.returnValue = false); 14 var menu = document.getElementById('myContextMenu'), 15 pageX = event.pageX?event.pageX:(event.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft)), 16 pageY = event.pageY?event.pageY:(event.clientY+(document.body.scrollTop||document.documentElement.scrollTop)); 17 menu.style.left = pageX+'px'; 18 menu.style.top = pageY+'px'; 19 menu.style.visibility = 'visible'; 20 }); 21 eventHandler(document,'click',function(event){ 22 document.getElementById('myContextMenu').style.visibility = 'hidden'; 23 }) 24 } 25 function eventHandler(dom,type,fn){ 26 if(typeof dom.addEventListener != 'undefined'){ 27 dom.addEventListener(type,fn,false); 28 }else if(typeof dom.attachEvent != 'undefined'){ 29 dom.attachEvent('on'+type,fn); 30 }else{ 31 dom['on'+type] = fn; 32 } 33 } 34 </script> 35 </head> 36 <body> 37 <ul id='myContextMenu' style="padding:0;margin:0;list-style:none;position:absolute;visibility:hidden;background-color:silver;"> 38 <li>hi</li> 39 <li><a href="#">hello</a></li> 40 </ul> 41 <div>asdfasf</div> 42 <div>asdfasf</div> 43 <div>asdfasf</div> 44 <div>asdfasf</div> 45 <div>asdfasf</div> 46 <div>asdfasf</div> 47 <div>asdfasf</div> 48 <div>asdfasf</div> 49 <div>asdfasf</div> 50 <div>asdfasf</div> 51 <div>asdfasf</div> 52 <div>asdfasf</div> 53 <div>asdfasf</div> 54 <div>asdfasf</div> 55 <div>asdfasf</div> 56 <div>asdfasf</div> 57 </body> 58 </html>