异步加载数据的 js tree (基于Jquery)

  在网页中经常要用到显示拥有层级关系的数据,比如信息发布网站的栏目菜单、某单位的组织结构等等。对于这类数据一般采用树形结构来显示,这样结构清晰明了,操作方便。在asp.net中有TreeView的组件,它的功能已经比较强大。但往往针对不同的项目的时候,他的扩展性,维护性个人感觉不太好。所以在自己写了一个基于jquery 的树js组件,事实完全可以抛离jquery用javascript就行,自己还是懒了点。

  这个组件只能以异步的方式加载数据,自己没有写同步的。感觉同步加载数据的用处不是很大,不如一步到位直接写成异部的。组件是没有层级限制的。浏览器的兼容性自己只在IE10和Chrome 23中进行了测试,这里只想与大家分享设计的思路,至于真正的实用性,我自己的代码能力有限,其实不能得到什么很广泛的应用。

  基本的HTML代码如下:

1 <div class="div_item" spath="1.1">
2             <ul id="b7b16a42-060d-4395-b7db-6cc1434513e3" class="ul_item">
3                 <li class="ltr_expanded"></li>
4                 <li class="lim_expanded"></li>
5                 <li class="lte">黑龙江省</li>
6             </ul>
7         </div>

  这是tree中的一个单元,用ul元素 显示了该单元中整行的结构内容。如果添加子节点,只需要在<div class="div_item" spath="1.1">元素后面追加一个DIV元素即可,控制好DIV的左侧距离既可以清晰的显示属性结构。代码整体很简单,没什么好说的,直接贴出供大家参考:

treeSJ01.js

  1 /*!
  2  * 基于Jquery 的Tree插件
  3  * 只可以异步加载数据
  4  * 三角号箭头展开图标
  5  * Author:Jann
  6  * Date: 2012-11-15
  7  */
  8 $.fn.Tree = function (settings) {
  9     var dfop = {
 10         method: "POST",
 11         datatype: "JSON",
 12         url: "",
 13         paramValue: "",
 14         redirectListUrl: "",
 15         redirectEditUrlB: ""
 16     }
 17     $.extend(dfop, settings);
 18     var me = $(this);
 19     var id = me.attr("id");
 20     if (id == null || id == "") {
 21         id = "bbtree" + new Date().getTime();
 22         me.attr("id", id);
 23     }
 24     buildTreeNode(me, 1, dfop.paramValue);
 25     function buildTreeNode(objDiv, spath, parentID) {
 26         objDiv.after("<div id='tree_div_wait'></div>");
 27         asyncLoadNodeData(parentID, function (result) {
 28             if (result.length > 0) {
 29                 nodeBuild(objDiv, result, spath);
 30             }
 31         });
 32     }
 33     function nodeBuild(objectDiv, nodes, spath) {
 34         var html = [];
 35         var nodeLen = 0;
 36         if (spath != 1) {
 37             nodeLen = spath.split('.').length - 1;
 38         }
 39         html.push("<div style='clear:both;margin-left: 20px;'>");
 40         for (var i = 0; i < nodes.length; i++) {
 41             if (i == nodes.length - 1) {
 42                 slast = 1;
 43             }
 44             html.push("<div class='div_item' spath='" + spath + "." + (i + 1) + "'>");
 45             html.push("<ul id='" + nodes[i].TreeID + "' class='ul_item'>");
 46             if (nodes[i].HasChild == 1) {
 47                 html.push("<li class='ltr_collapsed'></li>");
 48             }
 49             else {
 50                 html.push("<li class='ltr_none'></li>");
 51             }
 52             html.push("<li class='lim_collapsed'></li>");
 53             html.push("<li class='lte'>" + nodes[i].Name + "</li>");
 54             html.push("</ul>");
 55             html.push("</div>");
 56         }
 57         html.push("</div>");
 58         $("#tree_div_wait").remove();
 59         objectDiv.after(html.join(""));
 60         for (var j = 0; j < nodes.length; j++) {
 61             $("div[spath='" + spath + "." + (j + 1) + "'] li:first:not([class='ltr_none'])")
 62                     .mouseenter(triangleME)
 63                     .mouseleave(triangleML)
 64                     .click(nodeClick);
 65         }
 66     }
 67     function asyncLoadNodeData(parentID, callback) {
 68         var _data = { parentid: parentID };
 69         $.ajax({
 70             type: dfop.method,
 71             url: dfop.url,
 72             data: _data,
 73             dataType: dfop.datatype,
 74             success: callback,
 75             error: function (e) {
 76                 alert("load data error!");
 77             }
 78         });
 79     }
 80     function nodeClick(e) {
 81         var itemContainer = $(this).parent().parent();
 82         var spath = itemContainer.attr("spath");
 83         var targetLI = e.target || e.srcElement;
 84         switch (targetLI.className) {
 85             case "ltr_collapsed_B":
 86                 $(this).removeClass("ltr_collapsed_B").addClass("ltr_expanded_B");
 87                 if ($("div[spath='" + spath + ".1']").length == 0) {
 88                     buildTreeNode(itemContainer, spath, $(this).parent().attr("id"));
 89                 }
 90                 else {
 91                     $("div[spath='" + spath + ".1']").parent().css("display", "block");
 92                 }
 93                 $(this).next().removeClass("lim_collapsed").addClass("lim_expanded");
 94                 break;
 95             case "ltr_expanded_B":
 96                 $(this).removeClass("ltr_expanded_B").addClass("ltr_collapsed_B");
 97                 $("div[spath='" + spath + ".1']").parent().css("display", "none");
 98                 $(this).next().removeClass("lim_expanded").addClass("lim_collapsed");
 99                 break;
100         }
101     }
102     function triangleME() {
103         var className = $(this).attr("class");
104         var newClassName = className + "_B";
105         $(this).removeClass(className).addClass(newClassName);
106     }
107     function triangleML() {
108         var className = $(this).attr("class");
109         var newClassName = className.replace('_B', '');
110         $(this).removeClass(className).addClass(newClassName);
111     }
112 }

TreeSJ.css

 1 body { font-size: 12px; }
 2 .ul_item { clear: both; margin: 0px; padding: 0px; }
 3     .ul_item li { list-style-type: none; float: left; height: 22px; display: block; line-height: 22px; background-position: center center; background-repeat: no-repeat;}
 4         .ul_item li.ltr_collapsed { width: 20px; background-image: url('images/itemCollapsedIcon.png'); }
 5         .ul_item li.ltr_collapsed_B { width: 20px; background-image: url('images/itemCollapsedIconB.png'); }
 6         .ul_item li.ltr_expanded { width: 20px; background-image: url('images/itemExpandedIcon.png'); }
 7         .ul_item li.ltr_expanded_B { width: 20px; background-image: url('images/itemExpandedIconB.png'); }
 8         .ul_item li.ltr_none { width: 20px; background-image: url(''); }
 9         .ul_item li.lim_collapsed { width: 20px; background-image: url('images/ext_n.png'); }
10         .ul_item li.lim_expanded { width: 20px; background-image: url('images/ext_y.png'); }
11         .ul_item li.lte { line-height: 25px; }
12 .div_item { float: left; clear: both; }
13 #tree_div_wait
14 {
15     height: 22px;
16     float: left;
17     clear: both;
18     width: 22px;
19     background-position: center center;
20     background-image: url('images/tree-wait.gif');
21     background-repeat: no-repeat;
22     margin-left:20px;
23 }

前台调用:

 1 <html>
 2 <head>
 3     <meta name="viewport" content="width=device-width" />
 4     <title>TreePage</title>
 5     <script src="~/Scripts/jquery-1.7.1.js"></script>
 6     <script src="~/Scripts/tree/treeSJ01.js"></script>
 7     <link href="~/Content/TreeSJ.css" rel="stylesheet" />
 8     <script>
 9         $().ready(function () {
10             $("#treediv").Tree({
11                 'url': '@Url.Action("GetData")',
12                 'paramValue':'00000000-0000-0000-0000-000000000000'
13             });
14         });
15     </script>
16 
17 </head>
18 <body>
19     <div id="treediv">
20     </div>
21 </body>
22 </html>

json 数据结构

1     public class Tree
2     {
3         public Guid TreeID { set; get; }
4         public string Name { set; get; }
5         public Guid ParentID { set; get; }
6         public string Url { set; get; }
7         public int HasChild { set; get; }
8     }

 

总结:自己以前写了一个带网格线、加好图标的Tree但是代码很罗嗦,所以又写了一个三角号标的。代码中有一个地方大家需要注意,就是在读取数据的时候用数据参数,自己写死为parentid,这样如果是不同的参数,就需要将treeSJ01.js文件中的参数名手动更改,我自己还没有找到很好的解决方法。

posted @ 2012-11-15 15:13  杨伟明  阅读(1489)  评论(0编辑  收藏  举报