上下文菜單就是用戶在頁面上單擊右鍵時所顯示的一組命令。微軟的MSDN有一個簡單的例子說明了怎樣建立自定義菜單。這裡,我們將通過XML的數據島來快速創建自定義的上下文菜單。XML數據島就是存在於Html文檔中的XML數據的一部分。通過XML文檔對象模型[XML document object model (DOM)],我們可以輕松地參考和引用XML裡的內容。我們這裡利用XML數據島來存儲上下文菜單的多個定義,其中的每一個定義都可以和文檔中的任一元素相聯系。在沒有定義的地方,將顯示默認的菜單。
Internet Explorer 5.0首次提出對上下文菜單和數據島的支持,我們的例子在除Internet Explorer 5.0及以上的浏覽器裡將自動被忽略。因此,如果你使用的浏覽器不是Internet Explorer 5.0及以上的版本,你將看不到任何效果,只能看到浏覽器的默認菜單。如果你使用的是Internet Explorer 5.0及以上的浏覽器,你可以在頁面上點擊鼠標右鍵來看效果。注意:點擊圖象和文字將顯示不同的菜單。下面我們進行分析:
第一步:定義菜單
定義菜單是在文檔XML數據島裡的進行的,你只需簡單地在Html文檔的HEAD部分包含XML文件即可。例如:可以定義如下:
<XML id="contextDef">
<XMLdata>
<contextmenu id="demo">
<item id="vIEwsource" value="查看源文件"/>
<item id="back" value="返回上頁"/>
</contextmenu>
<contextmenu id="demob">
<item id="menu1" value="菜單項1" />
<item id="menu2" value="菜單項2" />
</contextmenu>
</XMLdata>
</XML>
在這裡,帶ID屬性的<xml>根節點和<xmldata>節點是必須的[注意:在XML裡大小寫是敏感的]。一個contextmenu節點和它所包含的多個item節點定義了一個菜單。如果你要定義多個菜單,你只需定義多個contextmenu節點即可。contextmenu節點的id屬性和頁面中的相應元素相關聯,item節點的id屬性標明哪一個菜單項被我們選取。值得注意的是:在整個XML文檔裡,所有的ID屬性不能重名。item節點的value值就是要在菜單裡要顯示的文字。
第二步:和Html裡的元素相關聯
在上面的XML數據島裡,我們定義了兩個菜單demo和demob,要想和HTML裡的元素相關聯,只需簡單地把contextmenu的ID值和Html元素的contextmenu屬性相連接即可。
<P contextmenu="demo">這個段落顯示demo菜單的內容</P>
<IMG SRC="usedemob.gif" contextmenu="demob">
第三步:編寫點擊菜單項的執行的操作
當我們單擊菜單的每一個選項時,函數fnFireContext就被調用,並把代表所選菜單的一個對象參數傳過來。為了處理單擊的事件,只需編寫簡單的switch語句,根據不同的ID值執行不同的操作。例如:
function fnFireContext(oItem) {
switch (oItem.menuid) {
case "vIEwsource":
location.href = "vIEw-source:" + location.href
break;
case "back":
history.back()
break;
default:
alert("您選的是:\n" + oItem.menuid + "\nText: " +
oItem.innerText)
}
}
你可以根據自己的需要進行更改鼠標單擊事件的操作。
第四步:定義菜單外觀
定義外觀只需使用樣式單即可,下面我們給出完整的例子,你完全可以拷貝、粘貼來看到本例子的效果!![注意:浏覽器必需是IE5+]。
<Html>
<head>
<meta http-equiv="Content-Type" content="text/Html; charset=gb2312">
<style>
.menu{ cursor: hand;
display: none;
position: absolute;
top: 0; left: 0;
overflow: hidden;
background-color: "#CFCFCF";
border: "1 solid";
border-top-color: "#EFEFEF";
border-left-color: "#EFEFEF";
border-right-color: "#505050";
border-bottom-color: "#505050";
font: 10pt 宋體;
margin:0pt;padding: 2pt
}
.menu SPAN {width: 100%; cursor: hand; padding-left: 10pt}
.menu SPAN.selected {background: navy; color:white; cursor: hand}
</style>
<XML id="contextDef">
<XMLdata>
<contextmenu id="demo">
<item id="vIEwsource" value="查看源文件"/>
<item id="back" value="後退……"/>
<item id="meng" value="訪問【孟憲會之精彩世界】"/>
<item id="calculate" value="執行 JavaScript 代碼"/>
</contextmenu>
<contextmenu id="demob">
<item id="菜單項例子1" value="菜單項例子1" />
<item id="菜單項例子2" value="菜單項例子2" />
</contextmenu>
</XMLdata>
</XML>
<SCRIPT>
// 定義全局變量
var bContextKey=false;
function fnGetContextID(el) {
while (el!=null) {
if (el.contextmenu) return el.contextmenu
el = el.parentElement
}
return ""
}
function fnDetermine(){
oWorkItem=event.srcElement;
//鍵盤上的菜單鍵被按下時。
if(bContextKey==true){
//如果菜單的“狀態”為“false”
if(oContextMenu.getAttribute("status")=="false"){
//捕獲鼠標事件,以便和頁面交互。
oContextMenu.setCapture();
//根據鼠標位置,確定菜單位置。
oContextMenu.style.top=event.clIEntY + document.body.scrollTop +
1;
oContextMenu.style.left=event.clIEntX + document.body.scrollLeft +
1;
oContextMenu.innerHtml="";
//設定菜單的“狀態”為“true”
var sContext = fnGetContextID(event.srcElement)
if (sContext!="") {
fnPopulate(sContext)
oContextMenu.setAttribute("status","true");
event.returnValue=false;
}
else
event.returnValue=true
}
}
else{
// 如果鍵盤菜單鍵沒有按下,並且菜單的“狀態”為“true”。
if(oContextMenu.getAttribute("status")=="true"){
if((oWorkItem.parentElement.id=="oContextMenu") &&
(oWorkItem.getAttribute("component")=="menuitem")){
fnFireContext(oWorkItem)
}
// 當鼠標離開菜單或單擊菜單項後,重設菜單(隱藏)
oContextMenu.style.display="none";
oContextMenu.setAttribute("status","false");
oContextMenu.releaseCapture();
oContextMenu.innerHtml="";
event.returnValue=false;
}
}
}
function fnPopulate(sID) {
var str=""
var elMenuRoot =
document.all.contextDef.XMLDocument.childNodes(0).selectSingle
Node(''contextmenu[@id="'' + sID + ''"]'')
if (elMenuRoot) {
for(var i=0;i<elMenuRoot.childNodes.length;i++)
str+=''<span component="menuitem" menuid="'' +
elMenuRoot.childNodes[i].getAttribute("id") +
''" id=oMenuItem'' + i + ''>'' +
elMenuRoot.childNodes[i].getAttribute("value") +
"</SPAN><BR>"
oContextMenu.innerHtml=str;
oContextMenu.style.display="block";
oContextMenu.style.pixelHeight = oContextMenu.scrollHeight
}
}
function fnChirpOn(){
if((event.clientX>0) &&(event.clIEntY>0)
&&(event.clIEntX<document.body.offsetWidth)
&&(event.clIEntY<document.body.offsetHeight)){
oWorkItem=event.srcElement;
if(oWorkItem.getAttribute("component")=="menuitem"){
oWorkItem.className = "selected"
}
}
}
function fnChirpOff(){
if((event.clientX>0) && (event.clIEntY>0) &&
(event.clIEntX<document.body.offsetWidth) &&
(event.clIEntY<document.body.offsetHeight)){
oWorkItem=event.srcElement;
if(oWorkItem.getAttribute("component")=="menuitem"){
oWorkItem.className = ""
}
}
}
function fnInit(){
if (oContextMenu) {
oContextMenu.style.width=180;
oContextMenu.style.height=document.body.offsetHeight/2;
oContextMenu.style.zIndex=2;
//設置菜單樣式
document.oncontextmenu=fnSuppress;
}
}
function fnInContext(el) {
while (el!=null) {
if (el.id=="oContextMenu") return true
el = el.offsetParent
}
return false
}
function fnSuppress(){
if (!(fnInContext(event.srcElement))) {
oContextMenu.style.display="none";
oContextMenu.setAttribute("status","false");
oContextMenu.releaseCapture();
bContextKey=true;
}
fnDetermine();
bContextKey=false;
}
function Javameng(){
window.open("http://lucky.myrice.com","_blank","width=400,height=
400,top=20,left=20")
}
function fnFireContext(oItem) {
// 自定義上下文菜單項的功能
switch (oItem.menuid) {
case "vIEwsource":
location.href = "vIEw-source:" + location.href
break;
case "back":
history.back()
break;
case "meng":
location.href="http://lucky.myrice.com"
break;
case "calculate":
Javameng()
break;
default:
alert("你點擊的菜單項是:\n\n\n" + oItem.menuid +"啊!!!")
}
}
</SCRIPT>
<BODY onload="fnInit()" onclick="fnDetermine()" bgcolor="#ccffcc">
<div status="false" onmouseover="fnChirpOn()" onmouSEOut="fnChirpOff()" id="oContextMenu" class="menu"></div>這裡放你任意的其他的東西! ...<br>... 這裡放你任意的其他的東西! ...<br>... 這裡放你任意的其他的東西! ...<br><br>
<P contextmenu="demo">這裡是利用上下文菜單的裡子!你把鼠標移動到這裡,然後單擊鼠標又鍵,可以看到菜單內容?lt;br>這裡是利用上下文菜單的裡子!你把鼠標移動到這裡,然後單擊鼠標又鍵,可以看到菜單內容!<br>這裡是利用上下文菜單的裡子!
你把鼠標移動到這裡,然後單擊鼠標又鍵,可以看到菜單內容!<br>這裡是利用上下文菜單的裡子!你把鼠標移動到這裡,然後單擊鼠標又鍵,可以看到菜單內容!<br>這裡是利用上下文菜單的裡子!你把鼠標移動到這裡,然後單擊鼠標又鍵,可以看到菜
單內容!<br></p><p>你也可以把鼠標放到下面的圖象上面,點擊又鍵!<p>
<center><IMG SRC="http://lucky.myrice.com/Javabk1.jpg" contextmenu="demob">
</body>
</Html>
必須說明的是:你還可以自己定義菜單的無效[即變灰]的操作,也可以進一步定義更下一級的子菜單。這就只好留給你自己進行練習啦!:)