没想到有这么多的朋友关注的dTree,过几天在我的新博客http://www.xiaosilent.com再发表一些关于dTree的文章,并会将本文中的例子修正好放出来,和大家互相学习。
		
				由于最近收到不少朋友发来mail反应demo不能运行的问题,在这里再次提请各位看官注意:本文处提供下载的dtree不能直接运行,需要修改其中onreadystatechange 的具体实现  By xiaosilent 2007/11/20
		
		       由于手上的项目要用到目录树来显示分类信息,于是有机会了解了一下常用的目录树。Google了一下,结果并不是很多。最后圈定了dTree。因为它的功能不弱,使用也还是很方便的,但是dTree原来是一次性加载的,不能动态添加节点。但是,只要稍作修改,还是可以实现的。
首先来看看 dTree 到底是什么样的。
从http://www.destroydrop.com/javascripts/tree/下载回dtree.zip,整个压缩包15K不到,可谓是相当苗条的了。解压开,里面有一个名为img的文件夹,两个html文件和一个dtree.js以及dtree.css。我们需要关注的是example01.html文件和dtree.js两个文件。
关于dTree是如何工作的,这点我就不再赘述了。
看 dtree.js 里面的一小段代码
		
				 //
				 Adds a new node to the node array
				//
				 Adds a new node to the node array
				
						
						 
				
				
						
						 
						 dTree.prototype.add 
				=
				 
				function
				(id, pid, name, url, title, target, icon, iconOpen, open)
dTree.prototype.add 
				=
				 
				function
				(id, pid, name, url, title, target, icon, iconOpen, open) 
				
						 {
				
				
						{

 this
						.aNodes[
						this
						.aNodes.length] 
						=
						 
						new
						 Node(id, pid, name, url, title, target, icon, iconOpen, open);
    
						this
						.aNodes[
						this
						.aNodes.length] 
						=
						 
						new
						 Node(id, pid, name, url, title, target, icon, iconOpen, open);

 }
				
				;
}
				
				;

 //
				 Outputs the tree to the page
				//
				 Outputs the tree to the page
				
						
						 
				
				
						
						 
						 dTree.prototype.toString 
				=
				 
				function
				()
dTree.prototype.toString 
				=
				 
				function
				() 
				
						 {
				
				
						{

 var
						 str 
						=
						 '
						<
						div class
						=
						"
						dtree
						"
						>
						\n';
    
						var
						 str 
						=
						 '
						<
						div class
						=
						"
						dtree
						"
						>
						\n';


 if
						 (document.getElementById)
    
						if
						 (document.getElementById) 
						
								 {
						
						
								{

 if
								 (
								this
								.config.useCookies) 
								this
								.selectedNode 
								=
								 
								this
								.getSelected();
        
								if
								 (
								this
								.config.useCookies) 
								this
								.selectedNode 
								=
								 
								this
								.getSelected();

 str 
								+=
								 
								this
								.addNode(
								this
								.root);
        str 
								+=
								 
								this
								.addNode(
								this
								.root);

 }
						
						 
						else
						 str 
						+=
						 'Browser not supported.';
    }
						
						 
						else
						 str 
						+=
						 'Browser not supported.';

 str 
						+=
						 '
						</
						div
						>
						';
    str 
						+=
						 '
						</
						div
						>
						';

 if
						 (
						!
						this
						.selectedFound) 
						this
						.selectedNode 
						=
						 
						null
						;
    
						if
						 (
						!
						this
						.selectedFound) 
						this
						.selectedNode 
						=
						 
						null
						;

 this
						.completed 
						=
						 
						true
						;
    
						this
						.completed 
						=
						 
						true
						;

 return
						 str;
    
						return
						 str;

 }
				
				;
}
				
				;
		 节点通过其add方法添加到目录树,而目录树是通过调用其 toString() 输出到页面,所有节点数据都保存在一个名为aNodes的数组里,随着程序的运行,数组里的数据会随之而发生变化,然而,要实现动态添加节点,就必须要保持原有的数据不变,这点,我们可以通过再添加一个数组来解决。让 add方法把数据添加到一个数组里,并让该数组的数据保持不变。而在toString方法里可以看到对addNode方法的调用,我们通过对该方法的修改,让其操纵另外的一个数组而不是add方法添加数据的那个。然后,再添加一个新方法,在该方法里完成将add方法操纵的数组内数据复制到另一数组的操作。修改toString方法,让其获取一个容器,并把str写入该容器。再添加一个getChildren方法,用来获取一个节点的子节点,并根据该节点是否有子节点而变化其图标。 
修改后的 dtree.js 如下(仅 修改的部分)

 /**//*--------------------------------------------------
/**//*--------------------------------------------------

 dTree 2.05 | www.destroydrop.com/javascript/tree/
    dTree 2.05 | www.destroydrop.com/javascript/tree/

 Rewrited by xiaosilent@gmail.com , xiangdingdang.com
    Rewrited by xiaosilent@gmail.com , xiangdingdang.com

 Last updated at 2007-4-28 16:32:05
    Last updated at 2007-4-28 16:32:05

 
    
 ---------------------------------------------------*/
---------------------------------------------------*/




 /**//**
/**//**
 * dTree
* dTree  
 *
*
 * Edited by xiaosilent.
* Edited by xiaosilent.
 *
* 
 * objName: name of dTree object . Create your dTree object like this   tree=new dTree('tree',*,*);
* objName: name of dTree object . Create your dTree object like this   tree=new dTree('tree',*,*);
 * targetID: the id of your container,which you used to display the tree
* targetID: the id of your container,which you used to display the tree
 * type: which kind of category are you doing with ? It must be one of these  "goods" , "vendor" and "consumer"
* type: which kind of category are you doing with ? It must be one of these  "goods" , "vendor" and "consumer" 
 *
*
 */
*/

 function dTree(objName,targetID,type)
function dTree(objName,targetID,type)  {
{
 
   

 this.config =
    this.config =  {
{
 
        
 target                    : null,
        target                    : null,
 
        
 // xiaosilent changed it to be false.
        // xiaosilent changed it to be false.
 folderLinks            : false,
        folderLinks            : false,

 useSelection        : true,
        useSelection        : true,
 
        
 
        
 
        
 
        

 }
    }
 
        
 // xiaosilent changed this to his own path.
    // xiaosilent changed this to his own path.

 this.icon =
    this.icon =  {
{
 
    
 
    
 
    
 };
    };
 
    

 this.obj = objName;
    this.obj = objName;

 this.aNodes = [];
    this.aNodes = [];
 
    
 // add by xiaosilent.
    // add by xiaosilent. 
 this.aNodesData=[];    //This array save the original data all the time.
    this.aNodesData=[];    //This array save the original data all the time.
 this.targetID=targetID||'dtree';    // Tree will be displayed in this container.
    this.targetID=targetID||'dtree';    // Tree will be displayed in this container.
 this.type=type;    // Saves the type of tree  goods/vendor/consumer?
    this.type=type;    // Saves the type of tree  goods/vendor/consumer?
 
    

 this.aIndent = [];
    this.aIndent = [];

 this.root = new Node(-1);
    this.root = new Node(-1);

 this.selectedNode = null;
    this.selectedNode = null;

 this.selectedFound = false;
    this.selectedFound = false;

 this.completed = false;
    this.completed = false;

 };
};


 // Adds a new node to the node array
// Adds a new node to the node array

 dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open)
dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open)  {
{
 
    
 // Add by xiaosilent.
    // Add by xiaosilent.
 this.completed = false;
    this.completed = false;
 
    
 this.aNodesData[this.aNodesData.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open);
    this.aNodesData[this.aNodesData.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open);

 };
};

 // Add by xiaosilent .
// Add by xiaosilent .
 // get child nodes from web server via AJAX automatically
// get child nodes from web server via AJAX automatically 
 // pid : parentID.
// pid : parentID.

 dTree.prototype.getChildren = function(pid)
dTree.prototype.getChildren = function(pid) {
{
 
    
 var ajax = null;
    var ajax = null;


 if (window.ActiveXObject)
    if (window.ActiveXObject)  {
{
 
    

 try
        try {
{
 
        
 ajax = new ActiveXObject("Microsoft.XMLHTTP");
            ajax = new ActiveXObject("Microsoft.XMLHTTP");
 
            

 }catch(e)
        }catch(e) {
{
 
        
 alert("创建Microsoft.XMLHTTP对象失败,AJAX不能正常运行.请检查您的浏览器设置.");
            alert("创建Microsoft.XMLHTTP对象失败,AJAX不能正常运行.请检查您的浏览器设置.");
 }
        }
 
        

 } else
    } else  {
{
 
    

 if (window.XMLHttpRequest)
        if (window.XMLHttpRequest)  {
{
 
            

 try
            try {
{
 
                
 ajax = new XMLHttpRequest();
                ajax = new XMLHttpRequest();
 
                

 }catch(e)
            }catch(e) {
{
 
            
 alert("创建XMLHttpRequest对象失败,AJAX不能正常运行.请检查您的浏览器设置.");
                alert("创建XMLHttpRequest对象失败,AJAX不能正常运行.请检查您的浏览器设置.");
 }
            }
 
            
 }
        }
 }
    }
 
    
 // This usr is just for my Sales Management System. This responses id,name,childCount|id,name,childCount
    // This usr is just for my Sales Management System. This responses id,name,childCount|id,name,childCount .
.
 var url ="/servlet/category?action=getChildren&parentID=" + pid +"&type=" + this.type;
    var url ="/servlet/category?action=getChildren&parentID=" + pid +"&type=" + this.type;
 
    
 var tree=this;
    var tree=this;
 
    

 ajax.onreadystatechange = function ()
    ajax.onreadystatechange = function ()  {
{
 
    

 if (ajax.readyState == 4&&ajax.status == 200)
        if (ajax.readyState == 4&&ajax.status == 200)  {
{
 
            
 if(ajax.responseText=="false") return;
            if(ajax.responseText=="false") return;
 
            
 var categories=ajax.responseText.split('|');
            var categories=ajax.responseText.split('|');
 
            

 for(var i=0;i<categories.length;i++)
            for(var i=0;i<categories.length;i++) {
{
 
            
 var aCat = categories[i].split(',');
                var aCat = categories[i].split(',');
 
                

 if(aCat.length==3)
                if(aCat.length==3) {
{
 
                    
 var id=aCat[0];
                    var id=aCat[0];
 var name=aCat[1];
                    var name=aCat[1];
 var childCount=aCat[2];
                    var childCount=aCat[2];
 
                    

 if(childCount>0)
                    if(childCount>0) {
{
 
                        
 tree.aNodesData[tree.aNodesData.length]=new Node(id, pid, name, "javascript:"+tree.obj+".getChildren("+id+")", "点击获取其子类",'',tree.icon.folder);
                        tree.aNodesData[tree.aNodesData.length]=new Node(id, pid, name, "javascript:"+tree.obj+".getChildren("+id+")", "点击获取其子类",'',tree.icon.folder);
 
                        

 }else
                    }else {
{
 
                        
 tree.aNodesData[tree.aNodesData.length]=new Node(id, pid, name, "javascript:"+tree.obj+".showCategory("+id+")", "点击获取详请");
                        tree.aNodesData[tree.aNodesData.length]=new Node(id, pid, name, "javascript:"+tree.obj+".showCategory("+id+")", "点击获取详请");
 
                        
 }
                    }
 }
                }
 }
            }
 
            
 tree.show();
            tree.show();
 }
        }
 
        
 };
    };
 
    
 ajax.open("POST",url);
    ajax.open("POST",url);
 ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
 ajax.send(null);
    ajax.send(null);
 
    
 }
}

 // Add by xiaosilent.
// Add by xiaosilent.
 // Call to show the tree.
// Call to show the tree.

 dTree.prototype.show = function()
dTree.prototype.show = function() {
{
 
    
 // Renew the two array to save original data.
    // Renew the two array to save original data.
 this.aNodes=new Array();
    this.aNodes=new Array();
 this.aIndent=new Array();
    this.aIndent=new Array();

 // Dump original data to aNode array.
    // Dump original data to aNode array.

 for(var i=0 ; i<this.aNodesData.length ; i++)
    for(var i=0 ; i<this.aNodesData.length ; i++) {
{
 
        
 var oneNode=this.aNodesData[i];
        var oneNode=this.aNodesData[i];

 this.aNodes[i]=new Node(oneNode.id,oneNode.pid,oneNode.name,oneNode.url,oneNode.title,oneNode.target,oneNode.icon,oneNode.iconOpen,oneNode.open);
        this.aNodes[i]=new Node(oneNode.id,oneNode.pid,oneNode.name,oneNode.url,oneNode.title,oneNode.target,oneNode.icon,oneNode.iconOpen,oneNode.open);
 }
    }
 
    
 this.rewriteHTML();
    this.rewriteHTML();
 }
}



 // Outputs the tree to the page , callled by show()
// Outputs the tree to the page , callled by show()
 // Changed by xiaosilent.
// Changed by xiaosilent.
 // Renamed dTree.prototype.toString to this.
// Renamed dTree.prototype.toString to this.

 dTree.prototype.rewriteHTML = function()
dTree.prototype.rewriteHTML = function()  {
{

 var str = '';
    var str = '';
 
    
 // Added by xiaosilent.
    // Added by xiaosilent. 
 var targetDIV;
    var targetDIV;
 targetDIV=document.getElementById(this.targetID);
    targetDIV=document.getElementById(this.targetID);
 
    

 if(!targetDIV)
    if(!targetDIV) {
{
 
        
 alert('dTree can\'t find your specified container to show your tree.\n\n Please check your code!');
        alert('dTree can\'t find your specified container to show your tree.\n\n Please check your code!');

 return;
        return;
 }
    }
 
    
 if (this.config.useCookies) this.selectedNode = this.getSelected();
    if (this.config.useCookies) this.selectedNode = this.getSelected();
 
    
 str += this.addNode(this.root);
    str += this.addNode(this.root);
 
        

 // Disabled by xiaosilent.
    // Disabled by xiaosilent.
 //    str += '</div>';
    //    str += '</div>';

 if (!this.selectedFound) this.selectedNode = null;
    if (!this.selectedFound) this.selectedNode = null;

 this.completed = true;
    this.completed = true;

 
    
 // Disabled and added by xiaosilent.
    // Disabled and added by xiaosilent.
 //return str;
    //return str;
 targetDIV.innerHTML=str;
    targetDIV.innerHTML=str;

 };
};

 // Highlights the selected node
// Highlights the selected node


 dTree.prototype.s = function(id)
dTree.prototype.s = function(id)  {
{
 
    

 if (!this.config.useSelection) return;
    if (!this.config.useSelection) return;

 var cn = this.aNodes[id];
    var cn = this.aNodes[id];

 if (cn._hc && !this.config.folderLinks) return;
    if (cn._hc && !this.config.folderLinks) return;
 
    
 // Disabled by xiaosilent.
    // Disabled by xiaosilent.

 };
};最后,客户端可以通过以下方式调用
 <div class="dtree" id="dtree1">
<div class="dtree" id="dtree1">


 <script type="text/javascript">
    <script type="text/javascript">

 d = new dTree('d',"dtree1",'goods');
        d = new dTree('d',"dtree1",'goods');

 d.add(0,-1,'点击展开商品分类信息',"javascript:d.getChildren(0)");
        d.add(0,-1,'点击展开商品分类信息',"javascript:d.getChildren(0)");
 
        
 d.show();
        d.show();


 </script>
    </script>

 </div>
</div>甚至可以在同一个页面里同时存在多个的tree,只要指定不同的容器,和创建不同的dtree对象即可。如:
 <div class="dtree" id="dtree2">
<div class="dtree" id="dtree2">


 <script type="text/javascript">
    <script type="text/javascript">

 w = new dTree('w',"dtree2",'consumer');
        w = new dTree('w',"dtree2",'consumer');

 w.add(0,-1,'点击展开客户分类信息',"javascript:w.getChildren(0)");
        w.add(0,-1,'点击展开客户分类信息',"javascript:w.getChildren(0)");
 
        
 w.show();
        w.show();


 </script>
    </script>

 </div>
</div>

 <div class="dtree" id="dtree3">
<div class="dtree" id="dtree3">


 <script type="text/javascript">
    <script type="text/javascript">

 z = new dTree('z',"dtree3",'vendor');
        z = new dTree('z',"dtree3",'vendor');

 z.add(0,-1,'点击展开商家分类信息',"javascript:z.getChildren(0)");
        z.add(0,-1,'点击展开商家分类信息',"javascript:z.getChildren(0)");
 
        
 z.show();
        z.show();


 </script>
    </script>

 </div>
</div>这样,虽然实现了节点的动态添加,但是,由于每次都要复制一次数组,程序执行的效率不高,期待更好的实现。
示例下载 需要有服务器提供正确的返回值才能正常运行……
	
posted on 2007-04-28 16:54 
xiaosilent 阅读(17616) 
评论(17)  编辑  收藏  所属分类: 
Java相关