用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"){