今天终于写好了这颗树,关于多级类别的显示管理的后台以及前台我都有了自己的东西。

大量参考meizz的树,有的函数直接拿来就用。数据结构不同,meizz是字符串存放数据,我是用2个数组(一个数据数组,一个索引数组),对于数据无需查找,直接引用。数据结构不同,所以核心实现过程不同,由于我确信这是一个高效率的数据结构,所以我自己写了这颗树。本意是在级联权限菜单管理界面使用的。因为我写自己的CMS的时候在这里停住了。

这颗树0.1版只实现了点击收起展开的功能,由于我用的代码少,只兼容ie,firefox,很容易调试,增加自己的功能。比如+个checkbox,以及增加对应的方法等...

meizz的树健壮是没有疑问的,我至今没有发现它出过问题,可惜别人的孩子,改起来总是费劲的。

本树,除了内核实现和meizz不同,图片,一些函数均大量的参考了meizz的树。

 
/**
* @描述 可无限级可选择的树
* @作者 bailing
* @创建时间 2006-03-06
* @修改时间 2006-03-20
* @version: 0.1  实现了树形显示,点击展开收起。
*
*
*/
function treeCheckBox( Tname  , rows , rowsPidIndex )
{
  
if(typeof(Tname) != "string" || Tname == "")
    
throw(new Error(-1, '创建类实例的时候请把类实例的引用变量名传递进来!'));
  
      
//【property】
      this.version                = '0.1'; //IE,FireFox兼容。2006-03-17
      this.name                    = Tname ;
      
this.topid                        = 0 ;
      
this.rows                    = rows ;
      
this.rowsPidIndex  = rowsPidIndex ;
      
this.deepLimit            = 0 ;
      
this.treeString        = '';
      
this.iconPath            = 'MzTreeView10/';
      
this.icons    = {
         L0        : 'L0.gif',  
//
         L1        : 'L1.gif',  //
         L2        : 'L2.gif',  //
         L3        : 'L3.gif',  //
         L4        : 'L4.gif',  //
         PM0       : 'P0.gif',  //+┏
         PM1       : 'P1.gif',  //+┣
         PM2       : 'P2.gif',  //+┗
         PM3       : 'P3.gif',  //+━
         empty     : 'L5.gif',     //空白图
         root      : 'root.gif',   //缺省的根节点图标
         folder    : 'book.gif', //缺省的文件夹图标
         file      : 'file.gif',   //缺省的文件图标
         exit      : 'exit.gif'
      };
      
this.iconsExpand = {  //存放节点图片在展开时的对应图片
         PM0       : 'M0.gif',     //-┏
         PM1       : 'M1.gif',     //-┣
         PM2       : 'M2.gif',     //-┗
         PM3       : 'M3.gif',     //-━
         folder    : 'bookopen.gif',
         exit      : 'exit.gif'
      };
}

//树的单击事件处理函数
treeCheckBox.prototype.clickHandle = function(e)
{
  e 
= window.event || e; e = e.srcElement || e.target;
  
//alert(e.tagName)
  switch(e.tagName)
  {
    
case "IMG" :
          pid
=e.parentNode.parentNode.id;
          pid
=pid.substr(pid.lastIndexOf("_"+ 1);
          
//alert(pid);
        this.expand(pid);
      
break;
    
case "A" :      
      
break;
    
case "SPAN" :
      
break;
    
default :
      
break;
  }    
};


/**
* 初始化树
* 画第一层节点
*/
treeCheckBox.prototype.toString 
= function( containObj )
{
     
this.setIconPath( this.iconPath );
     
this.setStyle();
     
var cid = this.topid;

 
var nodeImg = "<img id='"+this.name+"_node_pre_img_"+cid+"' src='"+this.icons.PM0.src+"'  />";
 
//alert(nodeImg);
    var    str ="<div class='boxTree' id='"+this.name+"_node_"+cid+"' class='TreeNode'  onclick="+this.name+".clickHandle(event)  noWrap>\n";
    str 
+="<NOBR>";    
    str 
+="<span id='"+this.name+"_node_cnt_"+cid+"' class='TreePreImg'>\n";
    str 
+="<span id='"+this.name+"_node_pre_"+cid+"'><span";
    str 
+="></span>";
    str 
+="<span>"+nodeImg+"</span>";
    str 
+="</span>";
    str 
+="</span>";
    str 
+="<span id='"+this.name+"_node_text_"+cid+"' class='TreeText'>root</span>";
    str 
+="</NOBR>";
    str 
+="<span id='"+this.name+"_node_son_"+cid+"' style='display:none'></span>";
    str 
+="</div>\n";
   containObj.innerHTML 
= str;
    mainIndex 
= this.rowsPidIndex[this.topid];
    
var hasChild = typeof(mainIndex)!='undefined';
    
if (hasChild)
    {
        
this.expand( this.topid );
        
//alert('');
    }
}

//点击展开树节点的对应方法
treeCheckBox.prototype.expand   = function( id )
{

var mainIndex = this.rowsPidIndex[id];
var hasChild = typeof(mainIndex)!='undefined'; 
 
var area  = document.getElementById(this.name +"_node_son_"+ id);
  
if (area && hasChild)
  {
      
//alert(id);
    var icon  = this.icons.PM1; //
    var iconE = this.iconsExpand.PM1; //-
    var expanded  = area.style.display != "none";
    
var img   = document.getElementById(this.name +"_node_pre_img_"+ id);
     
if( expanded ){
         
if( img.src==this.iconsExpand.PM1.src ){
            img.src
=this.icons.PM1.src
         }
else if( img.src==this.iconsExpand.PM2.src ){
            img.src
=this.icons.PM2.src
         }
else if( img.src==this.iconsExpand.PM0.src ){
            img.src
=this.icons.PM0.src
         }
     }
else {
         
if( img.src==this.icons.PM1.src ){
            img.src
=this.iconsExpand.PM1.src
         }
else if( img.src==this.icons.PM2.src ){
            img.src
=this.iconsExpand.PM2.src
         }     
else if( img.src==this.icons.PM0.src ){
            img.src
=this.iconsExpand.PM0.src
         }     
     }
      area.style.display 
= expanded ? "none" : "block";
     
//是否已经画过了
     var drawed = (area.childNodes.length>0);
     
if!expanded && !drawed){
         str 
= this.buildSon( id );
         area.innerHTML
=str;
     }
   }
else{
        
//如果没有子节点
        //alert('no child');
    }
 };

//画子节点。
treeCheckBox.prototype.buildSon   = function( id )
{
    
var pre=document.getElementById(this.name +"_node_pre_"+ id);
    
var imgpre   = pre.childNodes[0].innerHTML; //父id的前缀
    var sonStr='';
    
var str='';
    
var pIndex = this.rowsPidIndex[id];    
    
//alert(this.rowsPidIndex[id]);
    var totmain = pIndex.length-1;
    
var toti=0;
    
var isLast=false;
    
var preImg=imgpre;        
    
if(id!=this.topid)
    {
//如果非第一层节点,则均有其前缀。或为|或为空格
        var fatherId=this.rows[id][1];
        
var father = this.rowsPidIndex[fatherId];
        lastIdIndex 
= father.length-1;
        fatherLast 
= father[lastIdIndex];
        
var isLast = (id==fatherLast);
        
//alert(fatherLast+"\n"+fatherId+"\n"+lastIdIndex+"\n"+father.length+"\n"+father);
        if (!isLast) {
            imgTmp 
= "<IMG src='"+this.icons.L4.src+"' align=absMiddle>"
            preImg  
+= imgTmp  ;  //下一个前缀 │
        }
        
else {
            imgTmp 
= "<IMG src='"+this.icons.empty.src+"' align=absMiddle>"
            preImg  
+= imgTmp; //L5.gif.blank char
        }
    }    

    
for (var cidKey in pIndex)
    {
        
var cid = pIndex[cidKey];
        
//alert(cid);break;        
        var son = this.rowsPidIndex[cid];
        
var hasChild = typeof( son )!='undefined';

        
//节点前图片
        if (hasChild){//有子节点显示
            if (toti<totmain) {
                
var nodeImg = "<img id='"+this.name+"_node_pre_img_"+cid+"' src='"+this.icons.PM1.src+"'  />";
                
//├  +
            }
            
else {
                
var nodeImg = "<img id='"+this.name+"_node_pre_img_"+cid+"' src='"+this.icons.PM2.src+"'  />";
                
//└ +
            }
        }
        
else
        { 
//无子节点显示
            if (toti<totmain) {
                
var nodeImg = "<img id='"+this.name+"_node_pre_img_"+cid+"' src='"+this.icons.L1.src+"'  />";
                 
//
            }
            
else {
                
var nodeImg = "<img id='"+this.name+"_node_pre_img_"+cid+"' src='"+this.icons.L2.src+"'  />";
                
//
            }        
        }

        toti
++;
        str 
="<div id='"+this.name+"_node_"+cid+"' class='TreeNode'  noWrap>\n";
        str 
+="<div id='"+this.name+"_node_cnt_"+cid+"'>\n";
        str 
+="<NOBR>";
        str 
+="<span id='"+this.name+"_node_pre_"+cid+"'  class='TreePreImg'><span";
        str 
+=">"+preImg+"</span>";
        str 
+="<span>"+nodeImg+"</span>";
        str 
+="</span>";
        str 
+="<span id='"+this.name+"_node_text_"+cid+"' class='TreeText'>"+this.rows[cid][2]+"</span>";
        str 
+="</NOBR>";
        str 
+="</div>";
        str 
+="<div id='"+this.name+"_node_son_"+cid+"' style='display:none'></div>";
        str 
+="</div>\n";
        sonStr 
+=str;
    }
    
return sonStr;
};
 
/*
str +="<div id='tree_node_1' class='TreeNode'  noWrap>";
str +="<div id='tree_node_cnt_1'>";
str +="<NOBR>";
str +="<span id='tree_node_pre_1' class='TreePreImg'><span";
str +="><IMG src='' align=absMiddle></span>";
str +="<span><IMG id='tree_node_pre_img_1' src='' align=absMiddle></span>";
str +="</span>";
str +="<span id='tree_node_text_1' class='TreeText'>checkbox. a href..</span>";
str +="</NOBR>";
str +="</div>";
str +="<div id='tree_node_son_1' style='display:none'>子节点</div>";
str +="</div>";
 
*/

//本树将要用动的图片的字义及预载函数
//
path 图片存放的路径名
//
来自meizz的树,原封不动,预计将new image这个去掉。
treeCheckBox.prototype.setIconPath  = function(path)
{
  
var k = 0, d = new Date().getTime();
  
//te='';
  for(var i in this.icons)
  {
    
var tmp = this.icons[i];
    
this.icons[i] = new Image();
    
this.icons[i].src = path + tmp;
     
//te +=i+"\n";
  }
  
//alert(this.icons[i].toString());
  for(var i in this.iconsExpand)
  {
    
var tmp = this.iconsExpand[i];
    
this.iconsExpand[i]=new Image();
    
this.iconsExpand[i].src = path + tmp;
  }
};

//给树加上样式设置
treeCheckBox.prototype.setStyle = function()
{
  
var style = "<style>\n";
  style 
+=".TreeNode{clear:both;}\n";
  style 
+=".TreePreImg{float:left}\n";
  style 
+=".TreeText{float:left; height:20px; line-height: 20px;}\n";
  style 
+= "<\/style>";

  document.write(style);
};


test.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> checkbox树</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
*
{font:12px verdana; margin:0px; padding:0px;}
</style>
</head>

<body>
<script language="javascript" type="text/javascript" src="js/treeCheckBox.js"></script>
<div id="treeC"></div>
<script>
     
var rows = new Array; 
     
var rowsPidIndex = new Array; 
      rows[
4= new Array(4,3,'全局配置' ); 
      rows[
7= new Array(7,5,'安装' ); 
      rows[
8= new Array(8,3,'媒体管理' ); 
      rows[
9= new Array(9,0,'预览' ); 
      rows[
10= new Array(10,9,'在新窗口打开' ); 
      rows[
11= new Array(11,9,'嵌入窗口' ); 
      rows[
12= new Array(12,9,'嵌入窗口(位置)' ); 
      rows[
15= new Array(15,0,'模版管理' ); 
      rows[
16= new Array(16,15,'网站模版' ); 
      rows[
17= new Array(17,15,'安装' ); 
      rows[
19= new Array(19,15,'管理后台模版' ); 
      rows[
20= new Array(20,15,'安装' ); 
      rows[
22= new Array(22,15,'模块位置' ); 
      rows[
23= new Array(23,3,'回收站管理' ); 
      rows[
24= new Array(24,3,'用户管理' ); 
      rows[
65= new Array(65,34,'分类管理' ); 
      rows[
67= new Array(67,34,'首页管理' ); 
      rows[
68= new Array(68,34,'存档管理' ); 
      rows[
70= new Array(70,0,'组件' ); 
      rows[
71= new Array(71,70,'安装/卸载' ); 
      rows[
83= new Array(83,82,'管理广告位置.' ); 
      rows[
84= new Array(84,82,'Manage Banners.' ); 
      rows[
85= new Array(85,82,'Manage Clients.' ); 
      rows[
86= new Array(86,0,'com_rent' ); 
      rows[
87= new Array(87,86,'Rent.' ); 
      rows[
88= new Array(88,86,'Rent_Require.' ); 
      rows[
89= new Array(89,86,'Rent_Booking.' ); 
      rows[
99= new Array(99,0,'wap管理' ); 
      rows[
100= new Array(100,99,'管理类别.' ); 
      rows[
101= new Array(101,99,'管理餐厅.' ); 
      rows[
102= new Array(102,99,'词典管理.' ); 
      rows[
103= new Array(103,99,'管理内容.' ); 
      rows[
107= new Array(107,0,'企业组件' ); 
      rows[
111= new Array(111,107,'管理企业名录.' ); 
      rows[
112= new Array(112,107,'组件表管理.' ); 
      rows[
114= new Array(114,0,'模块' ); 
      rows[
115= new Array(115,114,'安装/卸载' ); 
      rows[
117= new Array(117,114,'网站模块' ); 
      rows[
118= new Array(118,114,'后台模块' ); 
      rows[
120= new Array(120,0,'触发器' ); 
      rows[
121= new Array(121,120,'安装/卸载' ); 
      rows[
123= new Array(123,120,'网站触发器' ); 
      rows[
125= new Array(125,0,'安装' ); 
      rows[
126= new Array(126,125,'模版 - 网站' ); 
      rows[
127= new Array(127,125,'模版 - 后台' ); 
      rows[
128= new Array(128,125,'语言' ); 
      rows[
130= new Array(130,125,'组件' ); 
      rows[
131= new Array(131,125,'模块' ); 
      rows[
132= new Array(132,125,'触发器' ); 
      rows[
136= new Array(136,134,'配置' ); 
      rows[
139= new Array(139,138,'全部放回' ); 
     rowsPidIndex[
3= new Array(4,8,23,24); 
     rowsPidIndex[
5= new Array('7'); 
     rowsPidIndex[
0= new Array(9,15,70,86,99,107,114,120,125); 
     rowsPidIndex[
9= new Array(10,11,12); 
     rowsPidIndex[
15= new Array(16,17,19,20,22); 
     rowsPidIndex[
34= new Array(65,67,68); 
     rowsPidIndex[
70= new Array('71'); 
     rowsPidIndex[
82= new Array(83,84,85); 
     rowsPidIndex[
86= new Array(87,88,89); 
     rowsPidIndex[
99= new Array(100,101,102,103); 
     rowsPidIndex[
107= new Array(111,112); 
     rowsPidIndex[
114= new Array(115,117,118); 
     rowsPidIndex[
120= new Array(121,123); 
     rowsPidIndex[
125= new Array(126,127,128,130,131,132); 
     rowsPidIndex[
134= new Array('136'); 
     rowsPidIndex[
138= new Array('139'); 
//alert( rowsPidIndex[70] );
var cTree = new treeCheckBox( 'cTree'  , rows , rowsPidIndex ); 
t
=document.getElementById('treeC');
cTree.toString(t);

function convert(){
t
=document.getElementById('treeC');
infoObj 
=document.getElementById('info');
infoObj.value
=t.innerHTML;
}
</script>
<input type="button"  value="-" onclick="convert();" />
<textarea name="" id="info" rows="10" cols="80" >
</textarea>
</body>
</html>
Posted on 2006-03-20 15:30  古代  阅读(549)  评论(1)    收藏  举报