首页 > 代码库 > 原创jquery插件treeTable(转)

原创jquery插件treeTable(转)

由于工作需要,要直观的看到某个业务是由那些子业务引起的异常,所以我需要用树表的方式来展现各个层次的数据。

需求:

         1、数据层次分明;

         2、数据读取慢、需要动态加载孩子节点;

         3、支持默认展开多少层。

     在网上找到了很多资料,发现treeTable方面的组件质量都不高,有些还不错样式不符合,性能也比较差。想想树表也挺简单的,不就是通过隐藏或者展现某些tr来实现嘛。于是乎,自己写一个。

 

      2011年5月4号恰好放假一个下午,于是在家里风风火火开始构造自己的树表插件。

      样式我就用了http://www.hanpau.com/index.php?page=jqtreetable,包括图片以及参数命名都借鉴了。但这款插件质量不怎样,使用方式很麻烦,效率低。

 

一、使用接口

     个人觉得,接口这部分是一款插件是否好用的核心。

 

  jqTreeTable的用法:

 

  html结构

  1. <span style="font-size: small;"><table id="id">  
  2. <tr><td>1</td></tr>  
  3. <tr><td>2</td></tr>  
  4. <tr><td>3</td></tr>  
  5. <tr><td>4</td></tr>  
  6. </table></span>  

 

  js调用

  1. <span style="font-size: small;">var map = [0, 1, 1, 0, 4, 5];  
  2. var options = {};  
  3. $("#id").jqTreeTable(map, options);</span>  

 

  这个使用方式比较麻烦,后台不仅要构造html,而且还要构造出map的数组。

 

 

 所以,我自己的组件改造了这种结构,如下:

 

   html结构

  1. <span style="font-size: small;"><table id="id">  
  2. <tr id="1"><td>1</td></tr>  
  3. <tr id="2" pId="1"><td>2</td></tr>  
  4. <tr id="3" pId="1"><td>3</td></tr>  
  5. <tr id="4" pId="3"><td>4</td></tr>  
  6. </table></span>  

 

   js调用

  1. <span style="font-size: small;">var options = {};  
  2. $("#id").jqTreeTable(options);</span>  

 

    我这种方式只需要构造html,把父子关系当作自定义属性放在html中,使用相对方便。(注意:我刚开始是使用 key="1" pKey="2"的方式来标识一行的数据,以及行之间的关系,但想到以后通过自定义属性key来选择行效率比较低,所以改为id来存储行的唯一标识。)

 

二、html的格式

    在jqTreeTable中:

<iframe id="iframe_0.625094280761427" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://zhanchaojiang.iteye.com/upload/picture/pic/89544/d8f9c83b-fa6f-3d55-9d5d-a6e4abc99865.png?_=3039486%22%20style=%22border:none;max-width:931px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.625094280761427‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>

 

    扣红的html对应的格式是:

  1. <span style="font-size: small;"><tr>  
  2. <td>6</td>  
  3. <td>  
  4. <img src=http://www.mamicode.com/"../images/vertline.gif" class="preimg">  
  5. <img src=http://www.mamicode.com/"../images/vertline.gif" class="preimg">  
  6. <img src=http://www.mamicode.com/"../images/blank.gif" class="preimg">  
  7. <img src=http://www.mamicode.com/"../images/tv-collapsable.gif" class="parimg" id="treet16">Child of 4  
  8. </td>  
  9. <td>[0, 2, 3, 4, 6]&nbsp;</td>  
  10. <td>4</td>  
  11. <td>[7]</td>  
  12. </tr></span>  

 

 这里有两个问题:

  1、都用图片在网速慢的情况时会产生很多图片占用符...,不好看。

  2、直接用图片会产生很多小图片,且不能合并。

 

以下是我优化的结构:

 

  1. <span style="font-size: small;"><tr>  
  2.     <td>6</td>  
  3.     <td>  
  4.         <span class="pre_span">  
  5.             <span class="vertline"></span>  
  6.             <span class="vertline"></span>  
  7.             <span class="blank"></span>  
  8.             </span>  
  9.         <span class="collapsable"></span>  
  10.          Child of 4  
  11.     </td>  
  12.     <td>[0, 2, 3, 4, 6]&nbsp;</td>  
  13.     <td>4</td>  
  14.     <td>[7]</td>  
  15. </tr></span>  

 

 这样解决了上述问题:

1、在网速慢的情况时只不过看不到背景,可不会出现图片占用符。

2、使用背景偏移的方式,可以把小图片合并在同张图片中。

 

三、原创treeTable的实现

基本逻辑

1、展开节点的图标有分最后一个跟非最后一个,例如:展开节点时最后一个的展开<iframe id="iframe_0.22480528574729997" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/picture/pic/89560/72d734a1-db58-3ade-aaa8-7ce935440138.gif?_=3039486%22%20style=%22border:none;max-width:931px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.22480528574729997‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>和最后一个的展开<iframe id="iframe_0.9461785487039656" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/picture/pic/89562/e36bf4b6-cb65-314b-801a-2cd86568986b.gif?_=3039486%22%20style=%22border:none;max-width:931px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.9461785487039656‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>。(需要isLastOne)

2、如果父节点是最后一个节点,则前缀加<iframe id="iframe_0.7482807651055776" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/picture/pic/89572/8ed2c5c8-088a-3ed2-84f2-75aa84fac52e.gif?_=3039486%22%20style=%22border:none;max-width:931px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.7482807651055776‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>,如果父节点不是最后一个节点,则前缀加<iframe id="iframe_0.8681787176770441" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/picture/pic/89548/0e13ff8d-4a1d-388b-a09c-7baf96725927.gif?_=3039486%22%20style=%22border:none;max-width:931px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.8681787176770441‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>。(需要isLastOne、hasChild)

3、如果有孩子,则显示+或-号,如果没有则是普通的叶子节点。(需要hasChild)

4、有孩子的节点点击则展开或者隐藏相应的子节点。(需要hasChild)
5、如果存在前一个兄弟节点,则使用节点的前缀图标,若不存在则用父节点的图标。(需要isFirstOne)
 

实现过程

1、在html中,我只是把父子节点的关系写在自定义属性,但对于节点是否有孩 子(hasChild),是否是最后一个节点(isLastOne),是否是第一个节点(isFirstOne),都还不知道。所以第一步要分析出这些信 息,把这些信息都记录到自定义属性。【注意:这些信息其实也可以记录到DOM对象的自定义属性中,但DOM对象的自定义属性无法在生成html的时候初始 化,所以不采用。】

2、先扫描所有的tr,构造出两个map,分别记录{‘pId‘ => [‘id1‘, ‘id2‘]}和{id => pId}的关系。

3、再次扫描所有的tr,根据两个map的关系,给tr增加hasChild、isLastOne、isFirstOne等自定义标签,并开始构造节点图标。

4、给整个table增加点击事件监控,如果是来自(hasChild)的父节点则进行点击事件。【亮点:jqTreeTable是给每个图标都绑定事件,而我是给整个table绑定一个点击事件,提高性能。】

 

最后效果:

<iframe id="iframe_0.44551890075164713" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://zhanchaojiang.iteye.com/upload/picture/pic/89600/79436569-5804-39c9-92e1-b12cf11bbd7b.png?_=3039486%22%20style=%22border:none;max-width:931px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.44551890075164713‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>

 

 

 

5月4号那天,花了下午完成基本功能,晚上一直自主加班到1点完善功能和优化性能,包括使用span替换img,使用table整体的点击事件等。为自己的执着而加班,最后效果还比较满意。还差将图片合并成一张,再改改css,就ok了。

 

 

 

 

原创jquery插件treeTable v1.1

这个版本提高了性能,做了以下改进:

 

* 1、使用了Css Sprite Tools 合并了分散的图标

* 2、使用了.id的方式来代替原来[pId=id],这样选择孩子效率更高

* 3、把css剥离出来,增加动态添加css,每次家在前判断是否添加过

 

关于第二点,非常感谢onli同学的提醒。但我并没有直接修改我的接口,直接除去pId,而是在第一次遍历时将pId作为class名添加到节点中。这样有两个好处:

(1)接口可读性会比较好,pId比class更容易理解。

(2)第二点,如果直接使用class,那节点本来就有样式,这样获取到的className还要去分解空格得到pId,挺麻烦的。

 

 

原创jquery插件treeTable V1.3

这个版本扩展了事件,做了以下改进:

* 1、增加onSelect事件,onSelect: function($treeTable, id){}

* 2、增加beforeExpand事件,beforeExpand : function($treeTable, id){}

 

动态加载节点就靠beforeExpand 事件了。

 

 

原创jquery插件treeTable V1.4.2

这个版本修复了bug,做了以下改进:

 

* 1、修复了多个tableTree不在同个页面的bug,并且可以让不同的tableTree使用不同的主题。

* 2、增加了controller的自定义标签来控制可点击的区域。

 

 

 转:http://zhanchaojiang.iteye.com/blog/1036454

 

  • treeTable.rar (35.1 KB)
  • 描述: treeTable V1.0
  • 下载次数: 210
  • treeTable_V1.1.rar (28.8 KB)
  • 下载次数: 54
  • treeTable_v1.3.rar (29.5 KB)
  • 下载次数: 87
  • treeTable_v1.4.2.rar (42.6 KB)
  • 下载次数: 716

原创jquery插件treeTable(转)