运用XML-XSL进行高级用户接口设计(1) - 目录树设计(范例已修正)
欢迎浏览《运用XML-XSL进行高级用户接口设计》系列。这里的每一篇文章都是Joe
Slovinski介绍并说明如何用XML和XSL技术构造特殊用途的用户接口(user interface, UI)组件。
本文说明如何用XML和XSL(XML样式表)来创建无限深度的目录树。本文提及的目录树各种功能,是由XML格式组成并经由XSL转换实现的,并将转换后的结果提交到用户界面。用户可以对树节点或对整棵树进行展开,收缩,全部展开,全部收缩的操作。本文示例适用于IE 5.5或以上版本。
目录树结构
跟其它许多Web对象一样,可以用各种方式来构造目录树。目录树结构有这样二种:
1、嵌套目录
2、线性目录
嵌套式目录
图1是非嵌套式目录,图2是嵌套式目录。通过嵌套式目录,可以清楚地看到文件对象模型(DOM)中各个对象之间的相互关系。
线性目录
线性目录能够提供良好的视觉效果,支持大结构目录模式,缺点是操作特性较差。一个有100条目录项的目录可能会用上300个图象来表达各个实体之间的关系。虽然使用缓存或者预加载会有所帮助,但它仍然还是体现DOM中的单个实体。不用线条,可以用空位来显示目录中的父子关系。本文将讨论这样的非线性目录的构造。
XML目录结构
各个用户要求的目录结构是大不相同的。XML为说明目录结构实体提供了非常完美的接口。在不同的XSL样式表和客户端操作下,选用的目录格式能够呈现不同的效果。我选定的目录格式能够被XSL递归调用,足以构造无限深度的目录。
我的XML目录结构由根节点"tree"开始,它只有一个实体(entity)元素。你可以在这里嵌套定义“内容”(contents)元素。下面是实体(entity)元素的子元素和属性说明。
名称 类型 说明
id 属性 实体标识符
description 元素 实体说明,对用户来说就是目录项
onClick 元素 客户端事件触发元素
image 元素 实体关闭或未被选择时的图象
imageOpen 元素 实体打开时的图象
contents 元素 包含实体元素。用于确定节点中是否有子节点
构造目录树时,用entity元素扩展树中的目录节点。标识可以是ID号或数据库中的相应标识符。我将在以后的文章中说明如何通过增加"oncontextmenu"元素来实现弹出式目录结构。
下面是本文使用到的XML文件。为了便于说明,我用静态XML文件,不用动态的XML数据库查询文件。
<?xml version="1.0"?>
<tree>
<entity id="e1">
<description>Customers</description>
<oncontextmenu></oncontextmenu>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity id="e2">
<description>Microsoft</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12345)</onClick>
<contents>
<entity id="e3">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
<entity id="e4">
<description>IBM</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12346)</onClick>
<contents>
<entity id="e5">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
<entity id="e6">
<description>Sun Microsystems</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12347)</onClick>
<contents>
<entity id="e7">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e8">
<description>#12345</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
<entity id="e9">
<description>#12346</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
<entity id="e10">
<description>Oracle</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12348)</onClick>
<contents>
<entity id="e11">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
<entity id="e12">
<description>Reports</description>
<oncontextmenu></oncontextmenu>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity id="e13">
<description>Income</description>
<oncontextmenu></oncontextmenu>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<contents>
</contents>
</entity>
<entity id="e14">
<description>Expenses</description>
<oncontextmenu></oncontextmenu>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<contents>
</contents>
</entity>
</contents>
</entity>
</tree> </JS>
上面这段代码存储为"tree.xml"文件,也可以在文末下载。
XSL样式表
图1和图2都是用XSL样式表将上面这段XML代码进行转换后生成的目录。以下是本文所用XSL文件:
<JS><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> </JS>
用XSL转换形成的目录如图3所示。
客户端操作
客户端的目录操作有这些功能:
初始化(Initialize )
目录扩展(Expand)
目录收缩(Collapse)
全部扩展(Expand All, Maximize)
全部收缩(Collapse All, Minimize)
下面是这5个函数的代码。可以在文末下载文件中的"tree.js"文件中找到。
<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技术的进步,我们可以在Web应用中维护系统的状态。可以把许多原先由服务端维护的工作转移到客户端来作,从而增加系统可维护性和系统功能。
今后我还要著文讲述如何创建API来动态地插入,删除,更名和刷新目录树节点对象。
例子下载
结语
希望这篇文章能够帮助你创建Web应用接口。如有疑问和建议请与我联系。
我将在下一篇文章中介绍如何创建弹出式菜单。
本文说明如何用XML和XSL(XML样式表)来创建无限深度的目录树。本文提及的目录树各种功能,是由XML格式组成并经由XSL转换实现的,并将转换后的结果提交到用户界面。用户可以对树节点或对整棵树进行展开,收缩,全部展开,全部收缩的操作。本文示例适用于IE 5.5或以上版本。
目录树结构
跟其它许多Web对象一样,可以用各种方式来构造目录树。目录树结构有这样二种:
1、嵌套目录
2、线性目录
嵌套式目录
图1是非嵌套式目录,图2是嵌套式目录。通过嵌套式目录,可以清楚地看到文件对象模型(DOM)中各个对象之间的相互关系。
线性目录
线性目录能够提供良好的视觉效果,支持大结构目录模式,缺点是操作特性较差。一个有100条目录项的目录可能会用上300个图象来表达各个实体之间的关系。虽然使用缓存或者预加载会有所帮助,但它仍然还是体现DOM中的单个实体。不用线条,可以用空位来显示目录中的父子关系。本文将讨论这样的非线性目录的构造。
XML目录结构
各个用户要求的目录结构是大不相同的。XML为说明目录结构实体提供了非常完美的接口。在不同的XSL样式表和客户端操作下,选用的目录格式能够呈现不同的效果。我选定的目录格式能够被XSL递归调用,足以构造无限深度的目录。
我的XML目录结构由根节点"tree"开始,它只有一个实体(entity)元素。你可以在这里嵌套定义“内容”(contents)元素。下面是实体(entity)元素的子元素和属性说明。
名称 类型 说明
id 属性 实体标识符
description 元素 实体说明,对用户来说就是目录项
onClick 元素 客户端事件触发元素
image 元素 实体关闭或未被选择时的图象
imageOpen 元素 实体打开时的图象
contents 元素 包含实体元素。用于确定节点中是否有子节点
构造目录树时,用entity元素扩展树中的目录节点。标识可以是ID号或数据库中的相应标识符。我将在以后的文章中说明如何通过增加"oncontextmenu"元素来实现弹出式目录结构。
下面是本文使用到的XML文件。为了便于说明,我用静态XML文件,不用动态的XML数据库查询文件。
<?xml version="1.0"?>
<tree>
<entity id="e1">
<description>Customers</description>
<oncontextmenu></oncontextmenu>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity id="e2">
<description>Microsoft</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12345)</onClick>
<contents>
<entity id="e3">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
<entity id="e4">
<description>IBM</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12346)</onClick>
<contents>
<entity id="e5">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
<entity id="e6">
<description>Sun Microsystems</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12347)</onClick>
<contents>
<entity id="e7">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents>
<entity id="e8">
<description>#12345</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
<entity id="e9">
<description>#12346</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
<entity id="e10">
<description>Oracle</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick>displayCustomer(12348)</onClick>
<contents>
<entity id="e11">
<description>Orders</description>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<onClick></onClick>
<contents/>
</entity>
</contents>
</entity>
</contents>
</entity>
<entity id="e12">
<description>Reports</description>
<oncontextmenu></oncontextmenu>
<image>images/book.gif</image>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity id="e13">
<description>Income</description>
<oncontextmenu></oncontextmenu>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<contents>
</contents>
</entity>
<entity id="e14">
<description>Expenses</description>
<oncontextmenu></oncontextmenu>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
<contents>
</contents>
</entity>
</contents>
</entity>
</tree> </JS>
上面这段代码存储为"tree.xml"文件,也可以在文末下载。
XSL样式表
图1和图2都是用XSL样式表将上面这段XML代码进行转换后生成的目录。以下是本文所用XSL文件:
<JS><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> </JS>
用XSL转换形成的目录如图3所示。
客户端操作
客户端的目录操作有这些功能:
初始化(Initialize )
目录扩展(Expand)
目录收缩(Collapse)
全部扩展(Expand All, Maximize)
全部收缩(Collapse All, Minimize)
下面是这5个函数的代码。可以在文末下载文件中的"tree.js"文件中找到。
<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技术的进步,我们可以在Web应用中维护系统的状态。可以把许多原先由服务端维护的工作转移到客户端来作,从而增加系统可维护性和系统功能。
今后我还要著文讲述如何创建API来动态地插入,删除,更名和刷新目录树节点对象。
例子下载
结语
希望这篇文章能够帮助你创建Web应用接口。如有疑问和建议请与我联系。
我将在下一篇文章中介绍如何创建弹出式菜单。
【内容摘要】欢迎浏览《运用XML-XSL进行高级用户接口设计》系列。这....
【关 键 字】网页设计
【本文网址】http://static.chinavisual.com/storage/contents/2002/06/10/3392T20020610014004_1.shtml
|
|||||







