欢迎访问:常州市武进区嘉泽中心小学网站 !今天是:
栏目列表
您现在的位置是:首页>>教师>>计算机技术>>网站制作技术>>文章内容
Navigation Tree 1.1 实现源码
发布时间:2008-11-20   点击:   来源:本站原创   录入者:佚名
 

Navigation Tree 1.1 实现详解

 

Navigation Tree 1.1是一个仿照 左侧目录树(如图所示,下称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="">

        <TreeNode Title="Node11" Href="" />

        <TreeNode Title="Node12" Href="about:blank" Target="_blank">

            <TreeNode Title="Node121" Href="mailto:s_yzzhou@{域名已经过期}" />

            <TreeNode Title="Node122" Href="javascript:alert('Hello,World');" Target="_self" />

            <TreeNode Title="Node123" Href="http://ebook.{域名已经过期}" />

        </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.{域名已经过期}" Target="_blank" />

    <TreeNode Title="Node5" />

</Tree>

 

格式转换文件(XSL):

用于格式化结点描述文件。

NavigationTree.xsl

<?xml version="1.0" encoding="utf-8" ?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://{域名已经过期}/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;

}

 

// OnBodyKeyDown()

// Handler of keydown event

function OnBodyKeyDown()

{

    var blnRetVal = false

    var objLI;

 

    if (window.event.ctrlKey == false && window.event.altKey == false)

    {

        window.event.cancelBubble = true;

        window.event.returnValue = false;

        switch (window.event.keyCode)

        {

        case 9 : // tab key

            if (window.event.shiftKey == true)

            {

                MovePrevious();

            }

            else

            {

                MoveNext();

            }

            break;

        case 13 : // enter key

            objLI = window.event.srcElement.parentElement;

            if(IsExpanded(lastClickedNode)){

                CollapseNode(lastClickedNode);

            }else{

                ExpandNode(lastClickedNode);

            }

            break;

        case 37 : // left key

            MoveLeft()

            break;

        case 38 : // up key

            MoveUp()

            break;

        case 39 : // right key

            MoveRight()

            break;

        case 40 : // down key

            MoveDown()

            break;

        case 188 : // "<" key

            MovePrevious();

            break;

        case 190 : // ">" key

            MoveNext();

            break;

        default :

            window.event.cancelBubble = false;

            window.event.returnValue = true;

            blnRetVal = true;

            break;

        }

    }

    else

    {

        window.event.cancelBubble = false;

        window.event.returnValue = true;

        blnRetVal = true;

    }

    return blnRetVal;

}

 

// Handler of onselectstart event

// Disable selection

function OnBodySelectStart()

{

    window.event.cancelBubble = true;

    window.event.returnValue = false;

    return false;

}

 

/*

End of event handlers

*/

////////////////////////////////////////////////////////

 

// Retrieve the parent document object with specified tag name.

function GetParentObject(obj,tag)

{

    if(obj){

        obj=obj.parentElement;

        while(obj&&obj.tagName.toUpperCase()!=tag.toUpperCase()){

            obj=obj.parentElement;

        }

        return obj;

    }

    return null;

}

 

// Retrieve the parent document object with specified tag name and type.

function GetParentElement(obj,tag,type)

{

    var parent=GetParentObject(obj,tag);

    while(parent&&!CheckItemType(parent,type)){

        parent=GetParentObject(parent,tag);

    }

    return parent;

}

 

// Retrieve the child document object with specified tag name and type.

function GetElement(parentObj,tag,type)

{

    if(type==null){

        type="";

    }

    if(parentObj!=null){

        var children=parentObj.children;

        if(children!=null){

            for(var i=0;i<children.length;++i){

                if(type==""){

                    if(CheckItemType(children(i),type)){

                        return children(i);

                    }

                }else{

                    if(children(i).tagName.toUpperCase()==tag &&

                        CheckItemType(children(i),type)){

                        return children(i);

                    }

                }

            }

        }

    }

    return null;

}

 

// Retrieve object's type if it has

function GetItemType(obj)

{

    if(obj){

        if(obj.type){

            return obj.type;

        }

    }

    return "";

}

 

// Verify object's type

function CheckItemType(obj,type)

{

    if(type==null){

        type="";

    }

    return GetItemType(obj).toUpperCase()==type.toUpperCase();

}

 

// Retrieve node item with a specified object within the node

function GetNode(obj)

{

    if(obj){

        if(CheckItemType(obj,"NODE")){

            return obj;

        }

        if(CheckItemType(obj,"LABEL")||CheckItemType(obj,"IMG")){

            while(obj&&CheckItemType(obj,"NODE")==false){

                obj=GetParentObject(obj,"DIV");

            }

            return obj;

        }

    }

    return null;

}

 

// Retrieve children container

function GetChildrenContainer(node)

{

    node=GetNode(node);

    if(node){

        var parent=GetElement(node,"DIV","nodecollection");

        return parent;

    }

    return null;

}

 

// Retrieve container in which the specified node resides in

function GetParentContainer(node)

{

    node=GetNode(node);

    if(node){

        var container=GetParentElement(node,"DIV","nodecollection");

        return container;

    }

    return null;   

}

 

// Retrieve the label of the specified node

function GetNodeLabel(node)

{

    var node=GetNode(node);

    if(node){

        return GetElement(node,"SPAN","LABEL");

    }

    return null;

}

 

// Retrieve the img of the specified node

function GetNodeImg(node)

{

    var node=GetNode(node);

    if(node){

        return GetElement(node,"SPAN","IMG");

    }

    return null;

}

 

// Retrieve the parent node

function GetParentNode(node)

{

    node=GetNode(node);

    if(node){

        var parent=GetParentElement(node,"DIV","nodecollection");//nodecollection

        if(parent){

            parent=GetParentElement(parent,"DIV","node");//parent's node

            return parent;

        }

    }

    return null;

}

 

// Retrieve first child node

function GetChildNode(node)

{

    node=GetNode(node);

    if(node){

        var container=GetChildrenContainer(node);

        if(container){

            return GetElement(container,"DIV","node");

        }

    }

    return null;

}

 

// Retrieve last child node

function GetLastChildNode(node)

{

    node=GetNode(node);

    if(node){

        var container=GetChildrenContainer(node);

        var children=container.children;

        if(children.length>0){

            return children(children.length-1);

        }

    }

    return null;

}

 

// Retrieve next sibling node

function GetNextSibling(node)

{

    node=GetNode(node);

    if(node){

        var container=GetParentContainer(node);

        if(container){

            var children=container.children;

            if(children&&children.length>0){

                var foundCurrent=false;

                for(var i=0;i<children.length;++i){

                    if(foundCurrent){

                        return children(i);

                    }

                    if(children(i)==node){

                        foundCurrent=true;

                    }

                }

            }

        }

    }

    return null;

}

 

// Retrieve previous sibling node

function GetPreviousSibling(node)

{

    node=GetNode(node);

    if(node){

        var container=GetParentContainer(node);

        if(container){

            var children=container.children;

            if(children&&children.length>0){

                var previous=null;

                for(var i=0;i<children.length;++i){

                    if(children(i)==node){

                        return previous;

                    }

                    previous=children(i);

                }

            }

        }

    }

    return null;

}

 

// Expand the specified node if it has children

function ExpandNode(node)

{

    node=GetNode(node);

    if(node&&HasChildren(node)){

        var img=GetNodeImg(node);

        if(img){

            img=GetElement(img,"SPAN","");

            if(img&&img.className.toUpperCase()!="CLSLEAF"){

                img.innerText="-";

                img.className="clsExpand";

            }

        }

        var container=GetChildrenContainer(node);

        if(container){

            container.className="shown";

        }

        if(container.nodesrc!=null){

            try{

                var source = new ActiveXObject("Msxml2.DOMDocument");

                source.async = false;

                source.resolveExternals = false;

                source.load(container.nodesrc);

               

                // Load style sheet.

                var stylesheet = new ActiveXObject("Msxml2.DOMDocument");

                stylesheet.async = false;

                stylesheet.resolveExternals = false;

                stylesheet.load(templatePath);

               

                var nodes=stylesheet.selectNodes("//xsl:template");

                for(var i=0;i<nodes.length;++i){

                    if(nodes(i).getAttribute("match")=="TreeNode"){

                        // "TreeNode" template found

                    }else{

                        // delete the other templates

                        stylesheet.documentElement.removeChild(nodes(i));

                    }

                }

                // Fill a div tag with the result of the transform

                container.innerHTML = source.transformNode(stylesheet);

                container.nodesrc=null;

            }catch(err){

                container.innerText=failureMsg;

                return;

            }  

        }

    }

}

 

// Collapse the specifed node if it has children

function CollapseNode(node)

{

    node=GetNode(node);

    if(node&&HasChildren(node)){

        var img=GetNodeImg(node);

        if(img){

            img=GetElement(img,"SPAN","");

            if(img&&img.className.toUpperCase()!="CLSLEAF"){

                img.innerText="+";

                img.className="clsCollapse";

            }

        }

        var container=GetChildrenContainer(node);

        if(container){

            container.className="hidden";

        }

    }

}

 

// Check whether a specified node has children nodes

function HasChildren(node)

{

    node=GetNode(node);

    if(node){

        var container=GetChildrenContainer(node);

        return container!=null;

    }

    return false;

}

 

// Check whether a specified node is expanded

function IsExpanded(node)

{

    node=GetNode(node);

    if(node){

        var container=GetChildrenContainer(node);

        if(container){

            if(container.className.toUpperCase()=="HIDDEN"){

                return false;

            }

            if(container.className.toUpperCase()=="SHOWN"){

                return true;

            }

        }

    }

    return false;

}

 

// Check wether a specified node is collapsed

function IsCollapsed(node)

{

    node=GetNode(node);

    if(node){

        var container=GetChildrenContainer(node);

        if(container){

            if(container.className.toUpperCase()=="HIDDEN"){

                return true;

            }

            if(container.className.toUpperCase()=="SHOWN"){

                return false;

            }

        }

    }

    return false;

}

 

// Open resource associated with a node

function NavigateNode(node)

{

    if(node){

        var label=GetNodeLabel(node);

        if(label){

            var a=GetElement(label,"A","");

            if(a){

                window.open(a.href,a.target);

            }

        }

    }

}

 

// Select specifed node

function SelectNode(node)

{

    node=GetNode(node);

    if(node!=lastClickedNode&&lastClickedNode){

        OnItemMouseDown(GetNodeLabel(node));

        OnItemMouseUp(GetNodeLabel(node));

    }

    NavigateNode(node);

}

 

// Move to previous sibling node when '<' key is pressed or 'shift+tab' pressed

function MovePrevious()

{

    if(lastClickedNode){

        var previous=GetPreviousSibling(lastClickedNode);

        if(previous){

            SelectNode(previous);

        }else{

            var parent=GetParentNode(lastClickedNode)

            if(parent){

                SelectNode(parent);

            }

        }

    }

}

 

// Move to first child node or next visible node when '>' key is pressed or 'tab' pressed

function MoveNext()

{

    if(lastClickedNode){

        var b=HasChildren(lastClickedNode);

        if(b){

            ExpandNode(lastClickedNode);

            var child=GetChildNode(lastClickedNode)

            SelectNode(child);

        }else{

            var next=GetNextSibling(lastClickedNode);

            if(next){

                SelectNode(next);

            }else{

                var parent=GetParentNode(lastClickedNode);

                while(parent){

                    next=GetNextSibling(parent);

                    if(next){

                        SelectNode(next);

                        break;

                    }

                    parent=GetParentNode(parent);

                }

            }

        }

    }

}

 

// Move to parent node

function MoveLeft()

{

    if(lastClickedNode){

        if(IsExpanded(lastClickedNode)){

            CollapseNode(lastClickedNode);

        }else{

            var parent=GetParentNode(lastClickedNode);

            if(parent){

                SelectNode(parent);

            }

        }

    }

}

 

// Move to first child node

function MoveRight()

{

    if(lastClickedNode){

        if(IsCollapsed(lastClickedNode)){

            ExpandNode(lastClickedNode);

        }else{

            var child=GetChildNode(lastClickedNode);

            if(child){

                SelectNode(child);

            }

        }

    }

}

 

// Move to last visible node

function MoveUp()

{

    if(lastClickedNode){

        var previous=GetPreviousSibling(lastClickedNode);

        if(previous){

            while(HasChildren(previous)&&IsExpanded(previous)){

                previous=GetLastChildNode(previous);

            }

            if(previous){

                SelectNode(previous);

            }

        }else{

            var parent=GetParentNode(lastClickedNode);

            if(parent){

                SelectNode(parent);

            }

        }

    }

}

 

// Move to next visible node

function MoveDown()

{

    if(lastClickedNode){

        if(HasChildren(lastClickedNode)&&IsExpanded(lastClickedNode)){

            var child=GetChildNode(lastClickedNode);

            if(child){

                SelectNode(child);

            }

        }else{

            var next=GetNextSibling(lastClickedNode);

            if(next){

                SelectNode(next);

            }else{

                var parent=GetParentNode(lastClickedNode);

                while(parent){

                    next=GetNextSibling(parent);

                    if(next){

                        SelectNode(next);

                        break;

                    }

                    parent=GetParentNode(parent);

                }

            }

        }

    }

}

///////////////////////////////////////////

///////////////////////////////////////////

 

CSS样式表:

此样式表即为MSDN Library目录树的样式表。

BODY

{

    font-family: Verdana;

    cursor: default;

    font-size: 9pt;

}

 

tbody

{

    font-size: 9pt;

}

 

.NavigationTree

{

    padding: 4px 5px;

}

 

.Navigation IMG

{

    position: relative;

    cursor: hand;

    top: -2px;

    margin: 0px;

    padding: 0px;

}

 

 

.NavigationTree A

{

    color: black;

    text-decoration: none;

}

 

span

{

    padding: 2px 3px;

    position: relative;

    display: inline;

    top: -2px;

    height: 17px;

    border: solid 1px #f1f1f1;

}

 

 

 

span.clsLabel

{

}

SPAN.clsSpace

{

    font-family: verdana;

    position: relative;

    padding: 3px 2px;

    top: 0px;

    width: 17px;

    margin: 0px;

    cursor: hand;

    overflow: hidden;

}

 

span.clsSpace span

{

    position: relative;

    width: 11px;

    height: 11px;

    border: solid 1px black;

    background-color: #ffffff;

}

 

SPAN.clsCollapse

{

    line-height: 6px;

    font-size: 9px;

    overflow: hidden;

    padding: 1px;

}

 

SPAN.clsExpand

{

    padding-left: 1px;

    overflow: hidden;

    line-height: 3px;

    font-size: 13px;

    padding-top: 3px;

}

 

SPAN.clsLeaf

{

    overflow: visible;

    font-size: 9px;

    line-height: 3px;

    padding: 1px 0px 0px 3px;

}

 

SPAN.clsMouseOver

{

    background-color: #CCCCCC;

    border: 1px solid #999999;

}

 

SPAN.clsMouseDown

{

    background-color: #999999;

    border: 1px solid #999999;

}

 

SPAN.clsCurrentHasFocus

{

    background-color: #FFFFFF;

    border: 1px solid #999999;

}

 

SPAN.clsCurrentNoFocus

{

    background-color: #F1F1F1;

    border: 1px solid #999999;

}

 

 

A

{

    color: black;

    text-decoration: none;

}

 

span.clsUnavailable

{

    height: 0px;

    border: none;

    color: #888888;

}

 

.hidden

{

    display: none;

}

 

.shown

{

    display: block;

    margin-left: 15px;

}

 

NavigationTree 1.1的运行结果如下图所示:

 

NavigationTree 1.1运行环境:

由于客户端脚本里使用到了MSXML2,所以浏览器环境必须为IE5.01或以上版本。而其他浏览器版本的兼容性问题可以使用服务器端脚本来解决。一下ASP.NET代码判断客户端浏览器版本:

<script language="C#" runat="server">

string treeurl="NavigationTree.xml";

private void Page_Load(object sender, System.EventArgs e)

{

    if(Request.Browser.MajorVersion<=5&&Request.Browser.MinorVersion<0.01){

        treeurl=treeurl.Replace("xml","aspx");

    }

    Response.Redirect(treeurl);

}

</script>

 

Bug Reporting

S_yzzhou@{域名已经过期}


附件:
    关闭窗口
    打印文档
    账号登录
    保持登录 忘记密码?
    账号与武进教师培训平台同步