您的位置:首页 > 产品设计 > UI/UE

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

2008-06-12 23:51 127 查看
创建目录树

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

下载例子代码

简介

XML和XSL/XSLT是当今越来越流行的一种数据处理技术。本文是系列文章的第一篇,介绍如何用XML和XSL/XSLT设计和创建目录树。后续的每一篇文章都将介绍如何用XML和XSL/XSLT设计和创建一个特定的高级Web 应用程序用户界面对象。
本文创建的目录树层次可以是无限制的。其建立机制是通过特定的XSL风格页将定义好的目录树XML文件转换成满足要求的HTML推送给客户端浏览器(IE5.5+)显示。客户端负责处理所有对目录的操作,如展开/收缩、最大化/最小化子目录和整个目录结点。

目录树结构介绍

与建立大多数Web页面对象一样,用XML/XSLT创建目录树的方法有很多,关键是确定目录树的结构,如图一是本文创建的一个目录树例子:



图一 嵌套的目录树结构

目录树中使用线条主要是为了有一个较好的可视化效果。但反过来会影响性能。有100个项的树大概要用300个图像来显示实体间的关系。尽管可以使用缓冲和预先加载,但在DOM中仍然犹如单个对象。不使用线条,而用简单的缩进可以说明父子之间的关系。本文中拟使用不带线条的树结构。

描述目录树结构的XML 文件

目录树的结构根据需要可以是多种多样的。XML为我们提供了无数的可能性来描述树型目录界面的结构。你所选择的格式直接影响XSL风格页的行为和客户的操作。本文所选则的目录树格式比较适用于XSL进行递归处理,它能很好地满足和实现无限深度的目录树的需要。
本文范例构造的XML文档包含一个根元素"tree",这个根元素下只有一个元素"entity"。可以把它看成是目录树的一个节点,整个树的结构是通过在每一层的entity元素的"contents"子元素中嵌套的entity元素来实现的。下面是"entity"元素中包含的关键所有元素或属性的清单。

名称类型描述
id属性目录节点元素(entity)的id号,唯一标示一个节点
description元素显示给用户的文本,目录节点元素的描述
onClick元素客户端触发onClick事件的函数名
image元素当目录节点被关闭或出于非选中状态时要显示的图像
imageOpen元素当目录节点打开时显示的图像
contents元素包含目录节点元素,其内容用以确定目录节点元素是否有子元素
在这个树结构中,用entity元素来添加与每一个树节点有关的特定数据。这些特定的数据可以是entity所表示的数据库记录的ID。在后续文章中,我们还将探讨如何创建目录节点的上下文菜单。我们将添加另外一个元素"oncontextmenu"到entity元素中。
下面的XML是本文所使用的目录树结构XML文件。这是一个静态的XML文件,在实际使用中,它可能是一个从数据库记录查询中产生出来的XML文件。

<?xml version="1.0" encoding="gb2312"?>
<tree>
<entity id="e1">
<description>在线杂志</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity id="e2">
<description>第十二期</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e3">
<description>组件对象模型</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e4">
<description>OLE 编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
<entity id="e5">
<description>ATL编程</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e51">
<description>OLE 编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
<entity id="e52">
<description>ATL编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
<entity id="e3">
<description>dotNet框架</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e4">
<description>C# 编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
<entity id="e5">
<description>数据库编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
<entity id="e2">
<description>第十三期</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e3">
<description>组件对象模型</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e4">
<description>OLE 编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick>www.vckbase.com/index.html</onClick>
<contents/>
</entity>
<entity id="e5">
<description>ATL编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick>www.vckbase.com/index.html</onClick>
<contents/>
</entity>
</contents>
</entity>
<entity id="e3">
<description>dotNet框架</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e4">
<description>C# 编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
<entity id="e5">
<description>数据库编程</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
</contents>
</entity>
</tree>

上面这个XML文件名为tree.xml,包含在可下载的例子代码中。下面我们来讨论如何在客户端浏览器中显示这个目录结构。

XSLT 式样文件
图一就是用式样文件XSLT转换XML的结果,其代码全文如下,它是应用到目录树XML文档的标准XSL风格页:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" language="JavaScript">
<xsl:template match="tree">
<xsl:apply-templates select="entity"/>
</xsl:template>

<xsl:template match="entity">
<div onclick="window.event.cancelBubble = true;clickOnEntity(this);" onselectstart="return false" ondragstart="return false">
<xsl:attribute name="image"><xsl:value-of select="image"/></xsl:attribute>
<xsl:attribute name="imageOpen"><xsl:value-of select="imageOpen"/></xsl:attribute>
<xsl:attribute name="open">false</xsl:attribute>
<xsl:attribute name="id">f<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="open">false</xsl:attribute>
<xsl:attribute name="STYLE">
padding-left: 20px;
cursor: hand;
<xsl:if expr="depth(this) > 2">
display: none;
</xsl:if>
</xsl:attribute>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="middle">
<img border="0" id="image">
<xsl:attribute name="SRC">
<xsl:value-of select="image"/>
</xsl:attribute>
</img>
</td>
<td valign="middle" nowrap="true">
<xsl:attribute name="STYLE">
padding-left: 7px;
font-family: Verdana;
font-size: 11px;
font-color: black;
</xsl:attribute>
<xsl:value-of select="description"/></td>
</tr>
</table>
<xsl:apply-templates select="contents/entity"/>
</div>
</xsl:template>

</xsl:stylesheet>

客户端操作
为了让目录树按照我们自己的意图运行,还需要在客户端做一些工作:例如初始化、实现展开、收缩目录节点等功能……。归纳起来就是下面这些脚本函数:
Initialize 初始化
Expand 展开单个节点
Collapse 收缩单个节点
Expand All (Maximize) 展开所有节点
Collapse All (Minimize) 收缩所有节点
下面是以上五个客户端操作的详细脚本代码。它们都放在文件tree.js中。
function initialize() {
var xmlDoc
var xslDoc

xmlDoc = new ActiveXObject(''''Microsoft.XMLDOM'''')
xmlDoc.async = false;

xslDoc = new ActiveXObject(''''Microsoft.XMLDOM'''')
xslDoc.async = false;

xmlDoc.load("tree/tree.xml")
xslDoc.load("tree/tree.xsl")

folderTree.innerHTML = xmlDoc.documentElement.transformNode(xslDoc)
}

function clickOnEntity(entity) {
if(entity.open == "false") {
expand(entity, true)
}
else {
collapse(entity)
}
window.event.cancelBubble = true
}

function expand(entity) {
var oImage

oImage = entity.childNodes(0).all["image"]
oImage.src = entity.imageOpen
for(i=0; i < entity.childNodes.length; i++) {
if(entity.childNodes(i).tagName == "DIV") {
entity.childNodes(i).style.display = "block"
}
}
entity.open = "true"
}

function collapse(entity) {
var oImage
var i

oImage = entity.childNodes(0).all["image"]
oImage.src = entity.image

// 收缩和隐藏字节点
for(i=0; i < entity.childNodes.length; i++) {
if(entity.childNodes(i).tagName == "DIV") {
if(entity.id != "folderTree") entity.childNodes(i).style.display = "none"
collapse(entity.childNodes(i))
}
}
entity.open = "false"
}

function expandAll(entity) {
var oImage
var i

expand(entity, false)

// 展开子节点
for(i=0; i < entity.childNodes.length; i++) {
if(entity.childNodes(i).tagName == "DIV") {
expandAll(entity.childNodes(i))
}
}
}

随着Web技术的进步,维护Web应用程序的状态逐渐成为可能。更多的处理和操作将从服务器端移到客户端进行,从而减轻服务器的工作负担,使得我们的程序界面越来越复杂,同时,应用程序的可用性和性能也需要不断的改进。
希望本文能抛砖引玉,共同探讨目前比较时髦的XML/XSL技术,利用它们来提高Web应用程序界面的质量。我们将在下一篇文章中继续我们的主题,讨论如何在目录树中创建上下文菜单。(
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: