分享
 
 
 

用XML和XSLT进行高级的Web UI设计(二)

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

用XML和XSLT进行高级的Web UI设计(二)

编译:alpha2002

定制目录树的上下文菜单

本文要求读者熟悉JScript,MSXML,XSL/XSLT,DOM。

下载例子代码

这是系列文章的第二篇,主要介绍如何在目录树中创建上下文菜单。本文中所使用的目录树结构就是我们在前面第一篇文章中所创建的目录树结构。在它的基础上引入上下文菜单特性。

在Windows应用程序中,窗口对象的上下文菜单无处不在,只要将鼠标指针移到某个应用程序的窗口对象上,然后单击右键就可以弹出该对象的上下文菜单。对于不同的应用程序,以及同一个应用程序中不同的窗口对象来说,其上下文菜单是不一样的。早期的IE浏览器没有让开发人员创建对象上下文菜单的能力。自从引入的文档对象模型(DOM)之后。使得开发人员在Web应用程序中创建上下文菜单成为可能。

本文将示范如何用XML和XSLT针对特定对象创建定制的上下文菜单,并且菜单的级数是没有限制的。其建立机制与树型目录的建立一样,通过特定的XSL风格页将定义好的目录树XML文件转换成满足要求的HTML推送给客户端浏览器(IE5.5+)显示。客户端负责处理所有对菜单的导航操作。

Windows中的上下文菜单可以适用于任何Web页面对象。本文所创建的菜单是针对我们在上一篇文章中所创建的目录树增加的新UI特性。

在上一篇文章里,我们曾提到过只要在描述目录树结构的XML文件的entity元素中加入一个 "oncontextmenu" 元素,然后在这个元素里请求一个定制的XML上下文菜单描述文件。便可以轻松实现目录树的上下文菜单。菜单的源代码可以从本文的链接下载。

图一 目录树上下文菜单运行例子

描述上下文菜单结构的XML 文件

与描述目录树结构的XML文件类似,这里所选则的上下文菜单格式能很好地适用于XSLT进行递归处理,从而满足和实现层次无限的上下文菜单的需要。

上下文菜单结构的XML文档有一个根元素"menu",此根元素下包含一个元素"entity"。然后在"entity"元素中定义"contents"子元素,整个上下文菜单的结构是通过在每一层entity元素的"contents"子元素中嵌套的entity元素来实现的。下面是"entity"元素中包含的关键所有元素或属性的清单。

名称

类型

描述

id

属性

上下文菜单或菜单选项的id号,唯一标示

description

元素

描述菜单或菜单选项的说明文本

onClick

元素

客户端触发onClick事件的函数名

image

元素

表示菜单选项的图像

contents

元素

包含entity子元素,其内容用以确定嵌套的entity元素是否有上下文子菜单

下面是描述上下文菜单结构的XML文档,当用户在目录树的某个节点单击右键,便会弹出在此节点定义菜单。每一个节点的上下文菜单可以是用不同的XML文件描述。当然,这些菜单可以是动态的,比如从数据库中读出记录进行处理。

<?xml version="1.0" encoding="gb2312"?>

<menu>

<entity id="c1">

<description>添加一期在线杂志</description>

<image>images/add_small.gif</image>

<contents>

<entity id="c2">

<description>一般文章</description>

<image>images/spacer.gif</image>

<contents>

<entity id="c2">

<description>数据库</description>

<image>images/spacer.gif</image>

<contents>

</contents>

</entity>

<entity id="c3">

<description>COM/COM+</description>

<image>images/spacer.gif</image>

<contents>

</contents>

</entity>

</contents>

</entity>

<entity id="c3">

<description>个人专栏</description>

<image>images/spacer.gif</image>

<contents>

<entity id="c2">

<description>wangjun专栏</description>

<image>images/spacer.gif</image>

<contents>

</contents>

</entity>

<entity id="c3">

<description>hangwire专栏</description>

<image>images/spacer.gif</image>

<contents>

</contents>

</entity>

</contents>

</entity>

</contents>

</entity>

</menu>

上面这个XML 文件名为"contextOnlineJnlFolder.xml",可以在下载代码中找到。下面我们来讨论如何在客户端浏览器中显示目录树结构中的上下文菜单。

XSLT 风格页

下面是应用到上下文菜单XML文档的标准的XSLT风格页:

<xsl:stylesheet version="1.1"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:dt="urn:schemas-microsoft-com:datatypes">

<xsl:template match="menu">

<div style="position: absolute;">

<div onselectstart="return false" ondragstart="return false">

<xsl:attribute name="STYLE">

position: absolute;

background-color: #6699cc;

border:1px solid #99ccff;

</xsl:attribute>

<table border="0" cellspacing="0" cellpadding="1">

<tr>

<td>

<table border="0" cellspacing="0" cellpadding="0">

<xsl:apply-templates select="entity"/>

</table>

</td>

</tr>

</table>

</div>

<xsl:apply-templates select="entity/contents"/>

</div>

</xsl:template>

<xsl:template match="entity">

<TR>

<xsl:attribute name="selected">false</xsl:attribute>

<xsl:attribute name="background">#6699cc</xsl:attribute>

<xsl:attribute name="light">#99ccff</xsl:attribute>

<xsl:attribute name="titlebar">#5389bc</xsl:attribute>

<xsl:attribute name="image">images/<xsl:value-of select="image"/></xsl:attribute>

<xsl:attribute name="imageOpen">images/<xsl:value-of select="imageOpen"/></xsl:attribute>

<xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>

<xsl:attribute name="ONCLICK"><xsl:value-of select="onClick"/>;clean()</xsl:attribute>

<xsl:attribute name="ONMOUSEOVER">

contextHighlightRow(this);

<xsl:if test="contents/node()[count(child::*)>0]">

loadContextMenuSub(this)

</xsl:if>

</xsl:attribute>

<xsl:attribute name="ONMOUSEOUT">contextHighlightRow(this)</xsl:attribute>

<TD VALIGN="MIDDLE" ALIGN="CENTER" NOWRAP="true">

<xsl:attribute name="ONCLICK"><xsl:value-of select="@onmousedown"/></xsl:attribute>

<xsl:attribute name="STYLE">

background-color: #5389bc;

border-top:1px solid #5389bc;

border-bottom:1px solid #5389bc;

border-left:1px solid #5389bc;

padding-left: 4px;

padding-right: 4px;

padding-top: 4px;

padding-bottom: 3px;

cursor: default;

</xsl:attribute>

<IMG BORDER="0" HEIGHT="15" WIDTH="15">

<xsl:attribute name="SRC"><xsl:value-of select="image"/></xsl:attribute>

</IMG></TD>

<TD NOWRAP="true">

<xsl:attribute name="ONCLICK"><xsl:value-of select="@onmousedown"/></xsl:attribute>

<xsl:attribute name="STYLE">

font-family: Arial;

font-size: 11px;

font-weight: normal;

color: white;

background-color: #6699cc;

border-top: 1px solid #6699cc;

border-bottom: 1px solid #6699cc;

padding-top: 2px;

padding-bottom:2px;

padding-left: 6px;

padding-right: 8px;

cursor: default;

</xsl:attribute>

<xsl:value-of select="description"/></TD>

<TD VALIGN="middle" ALIGN="right" STYLE="padding-right: 6px;" NOWRAP="true">

<xsl:attribute name="ONCLICK"><xsl:value-of select="@onmousedown"/></xsl:attribute>

<xsl:attribute name="STYLE">

background-color: #6699cc;

border-top: 1px solid #6699cc;

border-bottom: 1px solid #6699cc;

border-right: 1px solid #6699cc;

padding-right: 5px;

</xsl:attribute>

<IMG BORDER="0" WIDTH="4">

<xsl:attribute name="SRC">

<xsl:choose>

<xsl:when test="contents/node()[count(child::*)>0]">

images/opensub.gif

</xsl:when>

<xsl:otherwise>

images/spacer.gif

</xsl:otherwise>

</xsl:choose>

</xsl:attribute>

</IMG></TD>

</TR>

</xsl:template>

<xsl:template match="contents">

<xsl:if test="count(child::*)>0">

<div onselectstart="return false" ondragstart="return false">

<xsl:attribute name="STYLE">

position: absolute;

background-color: #6699cc;

border:1px solid #99ccff;

display: none;

</xsl:attribute>

<xsl:attribute name="ID"><xsl:value-of select="../@id"/>Sub</xsl:attribute>

<table border="0" cellspacing="0" cellpadding="1">

<tr>

<td>

<table border="0" cellspacing="0" cellpadding="0">

<xsl:apply-templates select="entity"/>

</table>

</td>

</tr>

</table>

</div>

<xsl:apply-templates select="entity/contents"/>

</xsl:if>

</xsl:template>

</xsl:stylesheet>

图二 应用XSLT风格页显示的上下文菜单

用户端的操作

为了让目录树的上下文菜单按照我们思路运行,还需要在客户端做一些工作:例如加载菜单、加载子菜单、加亮菜单选项、清除打开的菜单等功能……。归纳起来就是下面这些脚本函数,这些函数的代码都在context.js文件中。

loadContextMenu 加载上下文菜单

loadContextMenuSub 加载上下文子菜单

contextHighlightRow 加亮菜单项

clean 清除打开的菜单项

returnContainer 辅助函数

这些函数的源代码如下:

var appState = new applicationState()

function applicationState() {

this.contextMenu = null

}

function loadContextMenu(path) {

var xmlDoc

var xslDoc

var contextMenu

if(path != "") {

xmlDoc = new ActiveXObject(''''Microsoft.XMLDOM'''')

xmlDoc.async = false;

xslDoc = new ActiveXObject(''''Microsoft.XMLDOM'''')

xslDoc.async = false;

xmlDoc.load(path)

xslDoc.load("context/context.xsl")

if(appState.contextMenu != null) appState.contextMenu.removeNode(true)

document.body.insertAdjacentHTML("beforeEnd", xmlDoc.documentElement.transformNode(xslDoc))

contextMenu = document.body.childNodes(document.body.childNodes.length-1)

contextMenu.style.left = window.event.x

contextMenu.style.top = window.event.y

appState.contextMenu = contextMenu

window.event.cancelBubble = true

}

}

function loadContextMenuSub(obj) {

var contextMenu

var parentMenu

parentMenu = returnContainer(obj)

contextMenu = document.all[obj.id + "Sub"]

contextMenu.style.display = "block"

contextMenu.style.top = obj.offsetTop + parentMenu.style.pixelTop

contextMenu.style.left = obj.offsetWidth + parentMenu.style.pixelLeft

parentMenu.subMenu = contextMenu

}

function contextHighlightRow(obj) {

var parentMenu

var subMenu

var i

parentMenu = returnContainer(obj)

if(obj.selected == "false") {

for(i=0; i < obj.childNodes.length; i++) {

obj.childNodes(i).style.borderTop = "1px solid white"

obj.childNodes(i).style.borderBottom = "1px solid white"

if(obj.childNodes(i).cellIndex == 0) {

obj.childNodes(i).style.borderLeft = "1px solid white"

}

else if (obj.childNodes(i).cellIndex == obj.cells.length-1) {

obj.childNodes(i).style.borderRight = "1px solid white"

}

}

if(parentMenu.subMenu != null && parentMenu != parentMenu.subMenu) {

subMenu = parentMenu.subMenu

while(subMenu != null) {

subMenu.style.display = "none"

subMenu = subMenu.subMenu

}

}

obj.selected = "true"

}

else {

for(i=0; i < obj.childNodes.length; i++) {

if(i == 0) {

obj.childNodes(i).style.borderTop = "1px solid " + obj.titlebar

obj.childNodes(i).style.borderBottom = "1px solid " + obj.titlebar

}

else {

obj.childNodes(i).style.borderTop = "1px solid " + obj.background

obj.childNodes(i).style.borderBottom = "1px solid " + obj.background

}

if(obj.childNodes(i).cellIndex == 0) {

obj.childNodes(i).style.borderLeft = "1px solid " + obj.titlebar

}

else if (obj.childNodes(i).cellIndex == obj.cells.length-1) {

obj.childNodes(i).style.borderRight = "1px solid " + obj.background

}

}

obj.selected = "false"

}

}

function clean() {

var contextMenu

// remove and destroy context menu

if(appState.contextMenu != null) {

contextMenu = appState.contextMenu.removeNode(true)

contextMenu = null

}

}

function returnContainer(container) {

while(container.tagName != "DIV") {

container = container.parentNode

}

return container

}

菜单操作是很多Windows应用程序不可或缺的UI特性。希望通过本文提供的技术能进一步提高你的Web应用程序界面的质量。我们在下一篇文章中将继续上下文菜单的内容,讨论如何真正实现目录树上下文菜单的各种操作,如插入、修改、删除以及更改菜单项的名称等。(待续)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有