用XML数据岛创建上下文菜单

 
上下文菜单就是用户在页面上单击右键时所显示的一组命令。微软的 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.οncοntextmenu=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 οnlοad="fnInit()" οnclick="fnDetermine()" bgcolor="#ccffcc">
<div status="false" οnmοuseοver="fnChirpOn()" οnmοuseοut="fnChirpOff()" id="oContextMenu" class="menu"></div>
这里放你任意的其他的东西! ...<br>... 这里放你任意的其他的东西! ...<br>... 这里放你任意的其他的东西! ...<br><br>
<P contextmenu="demo">
这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容! <br> 这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容! <br> 这里是利用上下文菜单的里子!
你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容! <br> 这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容! <br> 这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜
单内容! <br></p><p> 你也可以把鼠标放到下面的图象上面,点击又键! <p>
<center><IMG SRC="http://lucky.myrice.com/javabk1.jpg"
 
contextmenu="demob">
</body>
</html>

必须说明的是:你还可以自己定义菜单的无效 [ 即变灰 ] 的操作,也可以进一步定义更下一级的子菜单。  
 
原文: http://www.cnitblog.com/piaoye12345/archive/2005/11/21/4770.aspx
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值