我的JS树(2)

在第一篇完成了树的基本展示后,终于有时间接着来完善用户交互部分了。这个版本的代码添加了

     1.展开/折叠功能,

     2.点击节点时触发相应事件

     如下:

计算机
编程语言
C语言
C语言程序设计
C#语言
设计模式
数学
社会学

      <script type="text/javascript">

        var Tree =
    {
        Resources:
        {
            Images:
            {
                TrunkNode:
                {
                    Expanded: 
"folder-open.gif",
                    Collapsed: 
"folder.gif"
                },
                LeafNode: 
"leaf.gif",
                Lines:
                {
                    Elbow: 
"elbow.gif",
                    ElbowEnd: 
"elbow-end.gif",
                    ElbowLine: 
"elbow-line.gif",
                    Blank: 
"blank.gif"
                }

            }
        },
        Styles:
        {
            NodeHeight: 
"16px"
        },
        Settings:
        {
            
///<summary>
            ///点击节点时触发
            ///</summary>
            OnNodeClick: function(node) {
                alert(node.innerText 
|| node.textContent);
            },
            Expanded: 
false
        },
        
///<summary>
        ///创建树
        ///<param name='nodes'>初始要加载的节点(节点的数组,可以使用js字面量也可以用数组:[{"ID":"1", "Name":"Node"}])</param>
        ///</summary>
        BuildTree: function(nodes, parentNode) {
            
if (nodes && nodes.length > 0) {
                
//Level 1
                for (var i = 0; i < nodes.length; i++) {
                    
var oNode = this._BuildNode(nodes[i], (i == nodes.length - 1? true : false, parentNode, this.Settings.Expanded);
                    
this._Fragment.appendChild(oNode);
                    
if (nodes[i].HasChild)//如果有子节点
                    {
                        
var childNodes = nodes[i].ChildNodes;
                        
this.BuildTree(childNodes, oNode);
                    }

                }
            }
            
this._InitEvent();
        },
        
        
///<summary>
        ///创建节点
        ///<param name="node">节点对象(可以是js字面量,也可以是一般的对象)</param>
        ///<param name="isLast">判断节点是否为同级的最后一个</param>
        ///<param name="parentNode">父节点</param>
        ///</summary>
        _BuildNode: function(node, isLast, parentNode, expanded) {
            
if (node) {
                
var oNode = document.createElement("div");
                oNode.style.height 
= this.Styles.NodeHeight;

                
var t = this;

                
if (node.HasChild) {
                    oNode.style.cursor 
= "pointer";
                }

                
if (parentNode) {
                    oNode.style.display 
= expanded ? "" : "none";
                }

                
//节点的完整路径,存储从最上层的节点一直到本节点的Index,是为了方便按照level来寻找节点对应level的祖先节点
                var nodePath = new Array();

                
if (parentNode && parentNode.NodePath && parentNode.NodePath.length > 0) {
                    
for (var i = 0; i <= parentNode.NodePath.length - 1; i++) {
                        nodePath.push(parentNode.NodePath[i]);
                    }

                }
                nodePath.push(t._Index);
                oNode.NodePath 
= nodePath;

                oNode.innerText 
= oNode.textContent = "";
                
//构造相对于父节点的连接线
                for (var i = 1; i < node.Level; i++) {
                    
var ancestorNode = t._Nodes[nodePath[i - 1]];
                    
var oImg = document.createElement("img");

                    oImg.src 
= ancestorNode.IsLast ? t.Resources.Images.Lines.Blank : t.Resources.Images.Lines.ElbowLine;
                    oNode.appendChild(oImg);
                }

                
//构造节点本身的连接线
                var elbowImg = document.createElement("img");
                
var elbowImgUrl = t.Resources.Images.Lines.Elbow;
                
if (isLast)//是同级的最后一个节点,则添加elbow-end.gif
                {
                    elbowImgUrl 
= t.Resources.Images.Lines.ElbowEnd;
                }
                elbowImg.src 
= elbowImgUrl;
                oNode.appendChild(elbowImg);

                
//构造节点类型图片
                var imgUrl = t.Resources.Images.TrunkNode.Collapsed;
                
if (node.IsLeaf) {
                    imgUrl 
= t.Resources.Images.LeafNode;
                }
                
var nodeTypeImg = document.createElement("img");
                nodeTypeImg.src 
= imgUrl;
                nodeTypeImg.NodeTypeImg 
= true;
                oNode.appendChild(nodeTypeImg);

                
//节点名字
                var oSpan = document.createElement("span");
                oSpan.innerText 
= node.Name;
                oSpan.textContent 
= node.Name;
                oSpan.Name 
= true;
                oNode.appendChild(oSpan);

                oNode.Index 
= t._Index;
                oNode.ParentNodeIndex 
= parentNode ? parentNode.Index : null;
                oNode.IsLast 
= isLast;
                oNode.IsLeaf 
= node.IsLeaf;
                oNode.Level 
= node.Level;
                oNode.Expanded 
= expanded;

                t._Nodes[t._Index] 
= oNode;
                t._Index
++;


                
return oNode;
            }

        },
        
///<summary>
        ///初始化节点的事件处理程序
        ///</summary>
        _InitEvent: function() {
            
var t = this;
            
for (var i = 1; i < t._Nodes.length; i++) {
                
var node = t._Nodes[i];
                
for (var j = 0; j < node.childNodes.length; j++) {
                    
if (node.childNodes[j].NodeTypeImg) {
                        node.childNodes[j].onclick 
= function() {
                            
var parentNode = this.parentNode;
                            
var childNodes;
                            
if (parentNode.Expanded) {//当前是展开的,需要隐藏后代节点
                                childNodes = t._FindDescendantNodes(parentNode);
                            }
                            
else {//当前是收缩的,只需展开子节点即可
                                childNodes = t._FindChildNodes(parentNode);
                            }
                            
for (var k = 0; k < childNodes.length; k++) {
                                childNodes[k].style.display 
= parentNode.Expanded ? "none" : "";
                            }
                            parentNode.Expanded 
= !parentNode.Expanded;
                        }
                    }
                    
else if (node.childNodes[j].Name) {
                        node.childNodes[j].onclick 
=
                        
function() {
                        t.Settings.OnNodeClick.call(
thisthis);
                        }
                    }
                }

            }

        },
        _Index: 
1,
        _Fragment: document.createDocumentFragment(),
        _Nodes: 
new Array(),
        
///<summary>
        ///寻找节点子节点
        ///</summary>
        _FindChildNodes: function(node) {
            
var result = [];
            
if (this._Nodes.length > 0) {
                
for (var i = 1; i < this._Nodes.length; i++) {
                    
if (this._Nodes[i].ParentNodeIndex == node.Index) {
                        result.push(
this._Nodes[i]);
                    }
                }
                
return result;
            }
        },
        
///<summary>
        ///寻找后代节点
        ///</summary>
        _FindDescendantNodes: function(node) {
            
var result = [];
            
if (this._Nodes.length > 0) {
                
for (var i = 1; i < this._Nodes.length; i++) {
                    
if (this._Nodes[i].NodePath.join(",").indexOf(node.NodePath.join(",")) == 0 && this._Nodes[i] != node) {
                        result.push(
this._Nodes[i]);
                    }
                }
                
return result;
            }
        }
    }
    
</script>
原文地址:https://www.cnblogs.com/jcomet/p/1693614.html