Navigation Tree 1.1 实现详解
Navigation Tree 1.1是一个仿照http://msdn.microsoft.com/library/ 左侧目录树(如图
所示,下称MSDN Library目录树)实现的居于XML的、客户端驱动的目录树组件。
Navigation Tree 1.0 写于2002年12月,当初的目的主要是为了获得与MSDN Library目录树相同的效果。1.1的更新版本完成于2003年1月20日,更新后的Navigation Tree 1.1功能支持动态加载目录结点,也修正了1.0里面一些按键事件的响应错误。Navigation Tree 1.1的表现MSDN Library目录树更加一致。
Navigation Tree分为四个部分:结点描述文件(XML)、格式转换文件(XSL)、JavaScript文件和CSS样式表。四部分的具体实现如下:
结点描述文件(XML):
描述树结点信息和结点之间的关系。
NavigationTree.xml
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="NavigationTree.xsl" ?>
<Tree>
<TreeNode Title="Node1" Href="http://www.china.com">
<TreeNode Title="Node11" Href="http://msdn.microsoft.com" />
<TreeNode Title="Node12" Href="about:blank" Target="_blank">
<TreeNode Title="Node121" Href="mailto:s_yzzhou@stu.edu.cn" />
<TreeNode Title="Node122" Href="javascript:alert('Hello,World');" Target="_self" />
<TreeNode Title="Node123" Href="http://ebook.stu.edu.cn" />
</TreeNode>
</TreeNode>
<TreeNode Title="Node2" Target="_blank">
<TreeNode Title="Node21" Target="_self" />
<TreeNode Title="Node22" Target="newFrame" />
</TreeNode>
<TreeNode Title="Node3" NodeSrc="NavigationTree.xml" />
<TreeNode Title="Node4" Href="http://ebook.stu.edu.cn" Target="_blank" />
<TreeNode Title="Node5" />
</Tree>
格式转换文件(XSL):
用于格式化结点描述文件。
NavigationTree.xsl
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Tree">
<html>
<head>
<title>NavigationTree</title>
<link rel="stylesheet" type="text/css" href="NavigationTree.css" />
<script language="javascript" src="NavigationTree.js" />
</head>
<body onselectstart="OnBodySelectStart();" onkeydown="OnBodyKeyDown();" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0" bgcolor="#f1f1f1" text="#000000">
<nobr>
<div class="NavigationTree" type="root">
<div type="nodecollection">
<xsl:apply-templates select="TreeNode" />
</div>
</div>
</nobr>
</body>
</html>
</xsl:template>
<xsl:template match="TreeNode">
<div type="node">
<!--Image-->
<span class="clsSpace" type="img">
<xsl:choose>
<xsl:when test="TreeNode or @NodeSrc">
<xsl:attribute name="onclick">OnImgClick(this)</xsl:attribute>
<xsl:attribute name="style">cursor:hand</xsl:attribute>
<span class="clsCollapse">+</span>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="style">cursor:default</xsl:attribute>
<span class="clsLeaf">.</span>
</xsl:otherwise>
</xsl:choose>
</span>
<!--Label-->
<span class="clsLabel" type="label" onclick="OnItemClick(this)" onmouseover="OnItemMouseOver(this)" onmouseout="OnItemMouseOut(this)" onmousedown="OnItemMouseDown(this)" onmouseup="OnItemMouseUp(this)">
<xsl:attribute name="id">
<xsl:value-of select="@NodeId" />
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="@Title" />
</xsl:attribute>
<xsl:choose>
<xsl:when test="@Href">
<xsl:attribute name="style">cursor:hand;</xsl:attribute>
<a>
<xsl:choose>
<xsl:when test="@Target">
<xsl:attribute name="target">
<xsl:value-of select="@Target" />
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="target">fraContent</xsl:attribute> <!--Change the target frame name to appropriate value-->
</xsl:otherwise>
</xsl:choose>
<xsl:attribute name="tabindex">-1</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="@Href" />
</xsl:attribute>
<xsl:value-of select="@Title" />
</a>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="style">cursor:default;</xsl:attribute>
<xsl:value-of select="@Title" />
</xsl:otherwise>
</xsl:choose>
</span>
<!--Child nodes-->
<xsl:if test="TreeNode or @NodeSrc">
<div class="hidden" type="nodecollection">
<xsl:choose>
<xsl:when test="@NodeSrc">
<xsl:attribute name="nodesrc">
<xsl:value-of select="@NodeSrc" />
</xsl:attribute>
<div type="node">
<span class="clsSpace" type="img" style="cursor:default">
<span class="clsLeaf">.</span>
</span>
<span class="clsUnavailable">Loading...</span> <!--Change the suggestive string to your language-->
</div>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="TreeNode" />
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:if>
</div>
</xsl:template>
</xsl:stylesheet>
JavaScript文件:
对文档事件进行处理。
NavigationTree.js
// Modify templatePath to the specified xsl file as you need
var templatePath="NavigationTree.xsl";
// Suggestive string for loading failure, Modify it to your language
var failureMsg="Failed to load child nodes.";
// Default window status message, Change it to your language
var defaultStatusMsg="Navigation Tree 1.1 -- [Kerry Chou]";
// Global variant for storing last clicked node item
var lastClickedNode=null;
//////////////////////////////////////////////////
/*
Beginning of event handlers
*/
// OnImgClick(obj)
// Handler of onclick event on img portion of a node
function OnImgClick(obj)
{
var node=GetNode(obj);
if(node){
if(!HasChildren(node)){
var label=GetNodeLabel(node);
if(label){
OnItemMouseDown(label);
OnItemClick(label);
OnItemMouseUp(label);
}
return;
}
if(IsExpanded(node)){
CollapseNode(node);
}else{
ExpandNode(node);
}
}
}
// OnItemClick(obj)
// Handler of onclick event on label portion of a node
function OnItemClick(obj)
{
var node=GetNode(obj);
var a=GetElement(obj,"A",null);
if(window.event.srcElement.tagName.toUpperCase()=="SPAN"){
NavigateNode(node);
}else{
document.body.focus();
}
if(node){
if(HasChildren(node)){
if(IsExpanded(node)){
CollapseNode(node);
}else{
ExpandNode(node);
}
}
}
}
// OnItemMouseDown(obj)
// Handler of onmousedown event
function OnItemMouseDown(obj)
{
if(obj){
obj.className="clsMouseDown";
}
if(lastClickedNode&&GetNodeLabel(lastClickedNode)!=obj){
GetNodeLabel(lastClickedNode).className="clsCurrentNoFocus";
}
}
// OnItemMouseUp(obj)
// Handler of onmouseup event
function OnItemMouseUp(obj)
{
if(GetNodeLabel(lastClickedNode)!=obj){
if(lastClickedNode){
GetNodeLabel(lastClickedNode).className="";
}
obj.className="clsCurrentHasFocus";
lastClickedNode=GetNode(obj);
}else{
obj.className="clsCurrentHasFocus";
}
}
// OnItemMouseOver(obj)
// Handler of onmouseover event
function OnItemMouseOver(obj)
{
if(obj&&obj!=GetNodeLabel(lastClickedNode)){
obj.className="clsMouseOver";
}
var a=GetElement(obj,"A",null);
if(a){
window.status=a.href;
}
}
// OnItemMouseOut(obj)
// Handler of onmouseout event
function OnItemMouseOut(obj)
{
if(obj&&obj!=GetNodeLabel(lastClickedNode)){
obj.className="";
}
window.status=defaultStatusMsg;
}
