分享
 
 
 

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

王朝other·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

作者:http://lucky.myrice.com

E-mail:amxh@21cn.com

--------------------------------------------------------------------------------

上下文菜单就是用户在页面上单击右键时所显示的一组命令。微软的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>这里放你任意的其他的东西! ...... 这里放你任意的其他的东西! ...... 这里放你任意的其他的东西! ...

<P contextmenu="demo">这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容!< br>这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容!这里是利用上下文菜单的里子!

你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容!这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜单内容!这里是利用上下文菜单的里子!你把鼠标移动到这里,然后单击鼠标又键,可以看到菜

单内容!</p><p>你也可以把鼠标放到下面的图象上面,点击又键!<p>

<center><IMG SRC="http://lucky.myrice.com/javabk1.jpg"

contextmenu="demob">

</body>

</html>

必须说明的是:你还可以自己定义菜单的无效[即变灰]的操作,也可以进一步定义更下一级的子菜单。这就只好留给你自己进行练习啦!:)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有