首页 > 代码库 > 我的开源框架之树控件

我的开源框架之树控件

需求:

1.根据无限级的树形结构的json生成树菜单

2.树样式可以是图标类型和简单类型

3.可以自定义节点的图标

4.支持复选框

5.支持懒加载方式请求数据

6.支持节点点击事件

7.只有右键菜单【未实现】

8.支持拖拽调整节点【未实现】

实现图例

客户代码

 1 <body> 2     <div id="Container" style="padding:10px; margin:0 auto;width:800px;height:300px;padding-top:10px;padding-left:100px"> 3         <ul id="tree"></ul> 4     </div> 5     <script type="text/javascript"> 6         function getAllCheckedNodes() { 7             var nodes =  tree.tree(‘getCheckNodes‘, ‘‘); 8             alert(JSON.stringify(nodes)); 9         }10         var data =http://www.mamicode.com/ [{11             "id1": "0",12             "text1": "菜单",13             "checked": true,14             "iconCls": "icon-ok",15             "children": [{16                 "id1": "0_1",17                 "text1": "子菜单1",18                 "checked": true,19                 "iconCls": "icon-save"20             }, {21                 "id1": "0_2",22                 "text1": "子菜单2",23                 "checked": true,24                 "iconCls": "icon-ok"25             }26             ]27         },{28             "id1": ‘2‘,29             "text1": "计算机语言",30             "closed": false,31             "children": [{32                 "id1": "2_1",33                 "text1": "Java",34                 "children": [{35                     "id1": ‘2_1_1‘,36                     "text1": ‘j2ee‘37                 }, {38                     "id1": ‘2_1_2‘,39                     "text1": ‘j2me‘,40                     "checked": true,41                     "iconCls": "icon-ok"42                 }, {43                     "id1": ‘2_1_3‘,44                     "text1": ‘jsp‘45                 }]46                 }, {47                     "id1": "2_2",48                     "text1": "C#"49                 }]50         }];51         var tree;52         $(function () {53             tree = $("#tree").tree({54                 onClick: function (data) {55                     console.log(JSON.stringify(data));56                     alert("click");57                 },58                 animate: true,59                 isPlain: false,60                 checkbox: true,61                 textField: ‘text1‘,62                 idField: ‘id1‘,63                 //data: data64                 lazy:true,                65                 url: ‘testServer/jsonQuestTest.ashx?flag=tree‘,66                 onl oadSuccess:function(data){67                     console.log("服务器数据返回:"+ JSON.stringify(data));68                 }                69             });70         });71     </script>72 </body>

组件代码:

  1 /**************************************************************  2 *作者:hjwen  3 *电邮:hjwen88@126.com  4 *版本:1.0  5 *版权许可:中国通用开源许可协议V1.0  6 *说明:tree组件  7 ***************************************************************/  8 (function ($) {  9     var isPlain = false, checkbox = false, animate = false, lazy = false; textField = ‘text‘, idField = ‘id‘, url=""; 10     var treeDataObj = null; var treeOpts = null; 11     var onl oadSuccess = null;//加载成功 12     function renderHtml(target) { 13         target.addClass(‘tree‘); 14         treeOpts = target.data(‘settings‘);        15         if (treeOpts.data =http://www.mamicode.com/= null) { 16             alert("treeOpts.data 是必须的!"); 17             return; 18         } 19         treeDataObj = treeOpts.data; 20         target.parent().css("overflow", "auto"); 21         isPlain = treeOpts.isPlain; 22         checkbox = treeOpts.checkbox; 23         animate = treeOpts.animate; 24         lazy = treeOpts.lazy; 25         url = treeOpts.url; 26         textField = treeOpts.textField; 27         idField = treeOpts.idField; 28         var treeJson = treeOpts.data; 29         var ctlData=http://www.mamicode.com/{isRoot:true,path:‘‘,pid:‘‘,isLastf:false,isFirstf:false,isRootFirst:false,isRootLast:false}; 30         loopInitCreate(treeJson, 1, target, ctlData); 31     }; 32     function loopInitCreate(treeJson, treeDeep, target,ctlData) { 33         var lastItem; 34         $.each(treeJson, function (i, node) { 35             var children = node.children; 36             node.idx = i; 37             node.pid = ctlData.pid; 38             var controlData = http://www.mamicode.com/{//控制参数 39                 isRoot: ctlData.isRoot,//是否是树根 40                 isFirst: false,//是否是第一个节点 41                 isLast: false,//是否是最后一个节点 42                 path: ctlData.path + i,//树路径,用于数据搜索,避免全树扫描性能问题 43                 isLeaf: false,//是否是子叶 44                 isLastf: ctlData.isLastf,//父元素是否为最后一个 ,第一级没有父元素为false 45                 isFirstf: ctlData.isFirstf,//父元素是否为第一个 ,第一级没有父元素为false 46                 treeDeep: treeDeep,//树深度 47                 isRootFirst: ctlData.isRootFirst,//是否是根第一个节点,用于控制节点图标和补充线的样式 48                 isRootLast: ctlData.isRootLast//是否是根最后一个节点,用于控制节点图标和补充线的样式 49             }; 50             if (i == 0) { 51                 if (ctlData.isRoot) 52                     controlData.isRootFirst = true; 53                 controlData.isFirst = true; 54             } 55             if (i == treeJson.length - 1) { 56                 controlData.isLast = true; 57                 if (ctlData.isRoot) 58                     controlData.isRootLast = true; 59             } 60             if (typeof children != ‘undefined‘ && $.isArray(children)) { 61                 var li = $("<li class=\"tree_li\"></li>").appendTo(target); 62                 if (children.length == 0) 63                     node.closed = true; 64                 lastItem = loopCreateTree(node, li, controlData); 65             } else {//子叶    66                 controlData.isLeaf = true; 67                 lastItem = createLeafNode(node, target, controlData); 68             } 69         }); 70         var tmpDeep = lastItem.attr("treedeep"); 71         var isleaf = lastItem.attr("isleaf"); 72         if (isleaf == ‘true‘){ 73             if(lastItem.attr("isrootlast")==‘true‘) 74                 lastItem.children("div:lt(" + tmpDeep + ")").removeClass("tree_line_all").addClass("tree_line_up"); 75         }else { 76             if (lastItem.attr("isclose") == ‘true‘){ 77                 lastItem.children("div:lt(" + tmpDeep + ")").removeClass("tree_collapsable_center").addClass("tree_collapsable_up"); 78                 lastItem.children("div:lt(" + (parseInt(tmpDeep)-1) + ")").removeClass("tree_line_all").addClass("tree_line_up"); 79             }                 80             else 81                 lastItem.children("div:lt(" + tmpDeep + ")").removeClass("tree_expandable_center").addClass("tree_expandable_up"); 82         } 83     } 84     /**********私有方法开始********************/ 85     /****远程加载数据*****/ 86     function queryData(params,loadingContaner, fn) { 87         var ajaxopt = { 88             url: url, 89             params: params, 90             loadingContainer: loadingContaner, 91             okdeal: function (data) { 92                 var arr = eval(data); 93                 fn(arr); 94                 if (typeof onl oadSuccess === ‘function‘) { 95                     onl oadSuccess(arr); 96                 } 97             } 98         };         99         $.myui.ajaxRequest(ajaxopt);100     };101     /*****102     *修改树数据的checked属性,注意非子叶节点的checked只做参考103     *@param path :节点的树路径,根据路径查找节点,避免全树搜索的性能开销104     *@param checked 是否选中105     ******/106     function modifyCheckAttr(path, checked) {107         var pathArr = path.split(‘_‘);  108         //利用setTimeout模拟开启一个更新数据的线程,加快处理速度109         setTimeout(function () {           110             //console.log("点击前数据=" + JSON.stringify(treeDataObj));111             loopCheckAttr(treeDataObj, pathArr, checked == ‘true‘);112             //console.log("更新后数据=" + JSON.stringify(treeDataObj));113         },0);  114     };115     function loopCheckAttr(dataArr, pathArr, checked) {116         for (var i = 0, len = dataArr.length; i < len; ++i) {117             if (pathArr[0] == i) {//已经找到 118                 dataArr[i].checked = checked;119                 if (pathArr.length > 1) {//根据path往下搜寻到末节点120                     if (typeof dataArr[i].children != ‘undefined‘ && $.isArray(dataArr[i].children)) {//如果有子集合121                         var tempArr = [];122                         for (var j = 0; j < pathArr.length; j++) {123                             if (j > 0)124                                 tempArr.push(pathArr[j]);125                         }126                         loopCheckAttr(dataArr[i].children, tempArr, checked);127                     }128                 } else {//如果已经找到路径的末点,并且点击的是非子叶节点则需要再往下更新数据                    129                     if (typeof dataArr[i].children != ‘undefined‘ && $.isArray(dataArr[i].children)) {130                         loopChildrenAttr(dataArr[i].children, checked);131                     }132                 }133                 break;134             }135         }136     };137     /****根据path获取点击节点的数据***/138     function getNodeByPath(dataArr, pathArr) {139         for (var i = 0, len = dataArr.length; i < len; ++i) {140             if (pathArr[0] == i) {//已经找到               141                 if (pathArr.length > 1) {//根据path往下搜寻到末节点142                     if (typeof dataArr[i].children != ‘undefined‘ && $.isArray(dataArr[i].children)) {143                         var tempArr = [];144                         for (var j = 0; j < pathArr.length; j++) {145                             if (j > 0)146                                 tempArr.push(pathArr[j]);147                         }148                         return getNodeByPath(dataArr[i].children, tempArr);149                     } 150                 } else {151                     return dataArr[i];152                 }153                 break;154             }155         }156     };157     /********根据path获取checked=true节点的数据***********/158     function getCheckedNodeByPath(dataArr, pathArr) {159         var res = [];160         if (pathArr.length ==1 && pathArr[0] == "") {161             $.each(dataArr, function (i, node) {162                 if (typeof node.children != ‘undefined‘ && $.isArray(node.children)) {163                     loopCheckedChildren(res, node.children);164                 } else {165                     if (node.checked)166                         res.push(node);167                 }168             });169         } else {170             var node = getNodeByPath(dataArr, pathArr);171             if (typeof node.children != ‘undefined‘ && $.isArray(node.children)) {172                 loopCheckedChildren(res, node.children);173             } else {174                 if (node.checked)175                     res.push(node);176             }177         }178         return res;179     };180     function loopCheckedChildren(res, nodes) {181         $.each(nodes, function (i,node) {182             if (typeof node.children != ‘undefined‘ && $.isArray(node.children)) {183                 loopCheckedChildren(res, node.children);184             } else {185                 if (node.checked)186                     res.push(node);187             }188         });189     };190     function loopChildrenAttr(children, checked) {191         $.each(children, function (j, node) {192             node.checked = checked;193             if (typeof node.children != ‘undefined‘ && $.isArray(node.children)) {194                 loopChildrenAttr(node.children, checked);195             }196         });197     };198     /****199     *复选框点击200     ****/201     function chkClick(e) {202         var t = $(this);203         var checked;204         var chkedString=‘true‘;205         var p = t.parent("div");206         if (t.hasClass("tree_chk_check_all"))//注意点击时,发现为选中状态的,将会变更为非选择状态207             chkedString = ‘false‘;208         modifyCheckAttr(p.attr("path"), chkedString);            209         if (p.attr("isleaf") == ‘true‘) {//子叶点击          210             if (t.hasClass("tree_chk_check_all")) {211                 checked = false;212                 p.attr("checkstate", "-1");213                 t.removeClass("tree_chk_check_all").addClass("tree_chk_uncheck");214             } else {215                 checked = true;216                 p.attr("checkstate", "1");217                 t.removeClass("tree_chk_uncheck").addClass("tree_chk_check_all");218             }219             loopCheckStyle(p.parent("li"), checked, 1);220         } else {221             var chkstate = p.attr("checkstate");222             if (chkstate == "1") {//如果是全选,在变为全取消223                 checked = false;224                 p.attr("checkstate", "-1");225                 p.attr("checkedcount", "0");226                 t.removeClass("tree_chk_check_all").addClass("tree_chk_uncheck");227                 //向下修改子节点228                 loopCheckChildStyle(p.next().children("li"), checked);229                 //向上修改父节点230                 if (p.attr("isroot")==‘false‘)231                     loopCheckStyle(p.parent("li"), checked, 1)232             } else {//变为全选状态233                 checked = true;234                 p.attr("checkstate", "1");235                 p.attr("checkedcount", p.attr("childcount"));236                 t.removeClass("tree_chk_uncheck").removeClass("tree_chk_check").addClass("tree_chk_check_all");237                 //向下修改子节点238                 loopCheckChildStyle(p.next().children("li"), checked);239                 //向上修改父节点240                 if (p.attr("isroot") == ‘false‘)241                     loopCheckStyle(p.parent("li"), checked, 1)242             } 243         }244         if (e && e.stopPropagation)245             e.stopPropagation();246         else247             window.event.cancelBubble = true;248     };249     function loopCheckChildStyle(childrens,checked) {250         $.each(childrens, function (i, node) {251             var $node = $(node).children("div");252             var chkIoc = $node.children(".tree_chk_ioc");253             if (checked) {254                 $node.attr("checkstate","1");255                 chkIoc.removeClass("tree_chk_uncheck").removeClass("tree_chk_check").addClass("tree_chk_check_all");256                 if ($node.attr("isleaf") == ‘false‘) {//非子叶节点257                     $node.attr("checkedcount", $node.attr("childcount"));258                     loopCheckChildStyle($node.next().children("li"), checked);259                 }260             } else {261                 $node.attr("checkstate", "-1");262                 chkIoc.removeClass("tree_chk_check_all").removeClass("tree_chk_check").addClass("tree_chk_uncheck");263                 if ($node.attr("isleaf") == ‘false‘) {//非子叶节点264                     $node.attr("checkedcount", "0");265                     loopCheckChildStyle($node.next().children("li"), checked);266                 }267             }           268         });269     }270     /***271    *递归check样式检查,并根据check状态修改图标样式272    *@param curLi 子叶项标签273    *@param checked 复选框 选中/不选中274    *@param count 加 减数量 275    ****/276     function loopCheckStyle(curLi, checked, count) {277         var p_ul = curLi.parent("ul");278         var titleObj = p_ul.prev();279         var fchkCount = parseInt(titleObj.attr(‘checkedcount‘));280         var fchildCount = parseInt(titleObj.attr(‘childcount‘));281         var fchkState = titleObj.attr(‘checkstate‘);282         var chkBoxDiv = titleObj.children(".chk_ioc");283         if (checked) {//如果是选中284             fchkCount = fchkCount + count;285             if (fchkCount > fchildCount)286                 fchkCount = fchildCount;287             titleObj.attr(‘checkedcount‘, fchkCount);288             // 修改父元素的 checkedcount checkstate 289             if (fchildCount == fchkCount) {290                 chkBoxDiv.removeClass("tree_chk_check");291                 chkBoxDiv.removeClass("tree_chk_uncheck");292                 chkBoxDiv.addClass("tree_chk_check_all");293                 titleObj.attr(‘checkstate‘, ‘1‘);294             } else {295                 chkBoxDiv.removeClass("tree_chk_uncheck");296                 chkBoxDiv.removeClass("tree_chk_check_all");297                 chkBoxDiv.addClass("tree_chk_check");298                 titleObj.attr(‘checkstate‘, ‘0‘);299             }300         } else {//取消选中301             fchkCount = fchkCount - count;302             if (fchkCount < 0)303                 fchkCount = 0;304             titleObj.attr(‘checkedcount‘, fchkCount);305             if (fchkCount == 0) {306                 titleObj.attr(‘checkstate‘, ‘-1‘);307                 chkBoxDiv.removeClass("tree_chk_check");308                 chkBoxDiv.removeClass("tree_chk_check_all");309                 chkBoxDiv.addClass("tree_chk_uncheck");310             } else {311                 chkBoxDiv.removeClass("tree_chk_uncheck");312                 chkBoxDiv.removeClass("tree_chk_check_all");313                 chkBoxDiv.addClass("tree_chk_check");314                 titleObj.attr(‘checkstate‘, ‘0‘);315             }316         } 317         //递归修改上一级父元素的状态318         if (titleObj.attr("isroot") == ‘false‘) {319             count = 0;320             if (titleObj.attr("checkstate") == "1" || titleObj.attr("checkstate") == "-1") {321                 count = 1;322             }323             loopCheckStyle(titleObj.parent("li"), checked, count);324         }        325     };326     /****327     *节点点击,展开/收起328     *****/329     function nodeClick(e) {330         var t = $(this);331         var p = t.parent("div");332         var ul = p.next();333         if (p.attr("isclose") == ‘false‘) {//收起334             p.children(".ioc_ioc").removeClass("tree_node_file_open").addClass("tree_node_file_close");//改变文件夹样式335             if (p.attr("isrootfirst") == ‘true‘ && p.attr("treedeep") == ‘1‘) {//如果是根节点336                 if (p.attr("islast")==‘true‘)337                     t.addClass("tree_collapsable_all");338                 else339                     t.addClass("tree_collapsable_down");340 341                 t.removeClass("tree_expandable_down");342             } else {343                 t.removeClass("tree_expandable_center");344                 if (p.attr("isrootlast") == ‘true‘ && p.attr("islast") == ‘true‘) {345                     if (p.attr("isfirst") == ‘true‘)346                         t.addClass("tree_collapsable_all");347                     else348                         t.addClass("tree_collapsable_up");349                 } else {350                     t.addClass("tree_collapsable_center");351                 }352             }353             if (p.attr("isrootlast") == ‘true‘ && p.attr("islast") == ‘true‘ && p.attr("islastf") == ‘true‘) {354                 p.children(".line_ioc").removeClass("tree_line_all").addClass("tree_line_up");355             }356             if (animate) {357                 ul.hide(300);358             } else {359                 ul.hide();360             }361             p.attr("isclose", ‘true‘);362         } else {//展开363             p.children(".ioc_ioc").removeClass("tree_node_file_close").addClass("tree_node_file_open");364             if (p.attr("isrootfirst") == ‘true‘ && p.attr("treedeep") == ‘1‘) {//如果是根节点365                 t.removeClass("tree_collapsable_down");366                 t.addClass("tree_expandable_down");367             } else {368                 if (p.attr("islast") == "true"){369                     t.removeClass("tree_collapsable_up");370                     t.prevAll().removeClass("tree_line_up").addClass("tree_line_all");371                 }                    372                 else373                     t.removeClass("tree_collapsable_center");374                 t.addClass("tree_expandable_center");375             }376             if (p.attr("isrootlast") == ‘true‘ && p.attr("islast") == ‘true‘ && p.attr("islastf") == ‘true‘) {377                 p.children(".line_ioc").removeClass("tree_line_up").addClass("tree_line_all");378             }379             if (animate) {380                 ul.show(300);381             } else {382                 ul.show();383             }384             p.attr("isclose", ‘false‘);385             if (lazy&&url!="") {386                 if (p.attr("childcount") == ‘0‘) {387                     var target = p.next("ul");388                     var loadingContaner = $("<li></li>").appendTo(target);389                     queryData("pid=" + p.attr("id"), loadingContaner, function (data) {390                         //将查询到的数据补充到treeDataObj,采用settimeout391                         setTimeout(function () {392                             var pathArr = p.attr("path").split("_");393                             //console.log("添加前数据=" + JSON.stringify(treeDataObj));394                             var findedNode = getNodeByPath(treeDataObj, pathArr);395                             findedNode.children = data;396                             //console.log("添加后数据=" + JSON.stringify(treeDataObj));397                         }, 0);398                         loadingContaner.remove();399                         p.attr("childcount", data.length);400                         var ctlData =http://www.mamicode.com/ {401                             isRoot: false,402                             path: p.attr("path") + "_",403                             pid: p.attr("id"),404                             isLastf: p.attr("islast")==‘true‘,405                             isFirstf: p.attr("isfirst") == ‘true‘,406                             isRootFirst: p.attr("isrootfirst") == ‘true‘,407                             isRootLast: p.attr("isrootlast") == ‘true‘408                         };409                         if (p.attr("isroot") == ‘true‘) {410                             ctlData.isRootFirst = ctlData.isFirstf;411                             ctlData.isRootLast = ctlData.isLastf;412                         }413                         loopInitCreate(data, parseInt(p.attr("treeDeep")) + 1, target, ctlData);414                     });415                 }             416             }417         }418         if (e && e.stopPropagation)419             e.stopPropagation();420         else421             window.event.cancelBubble = true;422     }423     /****424    *创建一个子节点425    *@param node 节点数据426    *@param target 节点目标容器427    *@param controlData 控制ui的数据428    *****/429     function createLeafNode(node, target, controlData) {430         /***********线样式***************/431         //根据树深度补充外围线 432         var lineCls = ‘‘, help = 1, fixLineDiv = ‘‘;433         if (controlData.isLast && controlData.isFirst && controlData.isRoot) {//只有一个子叶节点434             lineCls = "";435         } else {436             if (controlData.isLast && controlData.isRoot) {437                 lineCls = "tree_line_up";438             } else if (controlData.isFirst && controlData.isRoot) {439                 lineCls = "tree_line_down";440             } else {441                 if (controlData.isLast) {442                     lineCls = "tree_line_up";443                 } else {444                     lineCls = "tree_line_center";445                 }446             }447         }448         while (help <= controlData.treeDeep) {449             if (help == controlData.treeDeep) {//自身列450                 fixLineDiv = fixLineDiv + "<div class=\"tree_ioc_item tree_line_ioc " + lineCls + "\"></div>";451             } else {452                 fixLineDiv = fixLineDiv + "<div class=\"tree_ioc_item tree_line_ioc tree_line_all\"></div>";453             }454             help++;455         }456         /**************图标样式****************/457         var iconDiv = ‘‘;458         if (!isPlain) {//不是简单样式459             var iconCls = ‘tree_file_ioc tree_node_leaf‘;//默认的图标样式460             if (typeof node.iconCls == ‘string‘) {461                 iconCls = node.iconCls;462                 iconDiv = "<div style=\"background-position:0 2px;\" class=\"tree_ioc_item " + iconCls + "\"></div>";463             } else {464                 iconDiv = "<div class=\"tree_ioc_item " + iconCls + "\"></div>";465             }466         }467         /**************复选框样式***************/468         var chkBoxDiv = ‘‘, checkstate = ‘-1‘;469         if (checkbox) {470             var checked = node.checked;471             var chkCls = ‘tree_chk_uncheck‘;472             if (typeof checked == ‘boolean‘ && checked) {473                 chkCls = ‘tree_chk_check_all‘;474                 checkstate = ‘1‘;475             } else {476                 node.checked = false;//客户代码中没有checked,则补充上477             }478             chkBoxDiv = "<div class=‘tree_ioc_item tree_chk_ioc " + chkCls + "‘></div>";479         }480         var id = node[idField];481         var text = node[textField];482         var li_html = "<li class=\"tree_li\"><div treedeep=‘" + controlData.treeDeep + "‘ isfirstf=‘" + controlData.isFirstf + "‘ islastf=‘" + controlData.isLastf + "‘ isrootlast=‘" + controlData.isRootLast + "‘ isrootfirst=‘" + controlData.isRootFirst + "‘ path=‘" + controlData.path + "‘  checkstate=‘" + checkstate + "‘ pid=‘" + node.pid + "‘ isleaf=‘true‘ isLast=‘" + controlData.isLast + "‘ isfirst=‘" + controlData.isFirst + "‘ isroot=‘" + controlData.isRoot + "‘ treedeep=‘" + controlData.treeDeep + "‘ id=‘" + id + "‘ class=‘tree_ioc_wrap‘>" + fixLineDiv + iconDiv + chkBoxDiv + "<div class=‘tree_li_text‘>" + text + "</div></div></li>";483         var li = $(li_html).appendTo(target);484         var wrap = li.children("div");485         if (typeof treeOpts.onClick == ‘function‘) {486             wrap.bind(‘click‘, function () {487                var data = http://www.mamicode.com/getNodeByPath(treeDataObj,$(this).attr("path").split("_"));488                treeOpts.onClick(data);489             });490         }     491         if (checkbox) {492             var checked = node.checked;493             if (typeof checked == ‘boolean‘ && checked) {494                 loopCheckStyle(li, true, 1);495             }496             wrap.children(".tree_chk_ioc").bind(‘click‘, chkClick);497         }498         return li.children("div");499     };500 501     /****502    *循环递归创建一个父节点,这里肯定是子树503    *@param node 节点数据504    *@param target 节点目标容器505    *@param controlData 控制ui的数据506    *****/507     function loopCreateTree(nodef, target, controlData) {508         var treeJson = nodef.children;509         var iconDiv = "";510         var closed = false;511         if (typeof nodef.closed == ‘boolean‘)512             closed = nodef.closed;513         /************文件夹样式*****************/514         var lineCls, hideCls, help = 1, fixLineDiv = ‘‘, fixLineCls = ‘tree_line_all‘;515         if (closed) {//闭合状态516             hideCls = ‘display:none‘;517             if (controlData.isRoot && controlData.isFirst) {//根目录第一个节点            518                lineCls = ‘tree_collapsable_down‘;519             } else {520                 if (controlData.isFirst) {521                     lineCls = ‘tree_collapsable_down‘;522                 } else {523                     lineCls = ‘tree_collapsable_center‘;524                 }525             }526             //闭合状态下,要处理最后一个关闭节点的外围补充线样式问题527             if (controlData.isRootLast && controlData.isLast) {528                 fixLineCls = ‘tree_line_up‘;529                 lineCls = ‘tree_collapsable_up‘;530             }531         } else {//打开状态532             hideCls = ‘display:block‘;533             if (controlData.isRoot && controlData.isFirst) {//根目录第一个节点               534                 lineCls = ‘tree_expandable_down‘;             535             } else {536                 if (controlData.isFirst) {537                     lineCls = ‘tree_expandable_center‘;538                 } else {539                     lineCls = ‘tree_expandable_center‘;540                 }541             }542         }543         //根据树深度补充外围线            544         while (help <= controlData.treeDeep) {545             if (help == controlData.treeDeep) {546                 fixLineDiv = fixLineDiv + "<div class=\"node_ioc tree_ioc_item tree_line_ioc " + lineCls + "\"></div>"547             } else {548                 fixLineDiv = fixLineDiv + "<div class=\"line_ioc tree_ioc_item tree_line_ioc " + fixLineCls + "\"></div>";549             }550             help++;551         }552         /**************图标样式 *****************/553         if (!isPlain) {//不是简单样式554             var tmpCls;555             if (closed) {556                 tmpCls = "tree_node_file_close";557             } else {558                 tmpCls = "tree_node_file_open";559             }560             var iconCls = ‘tree_file_ioc ‘ + tmpCls;//默认的图标样式561             iconDiv = "<div class=\"ioc_ioc tree_ioc_item " + iconCls + "\"></div>";562         }563         /**************复选框******************/564         var chkBoxDiv = ‘‘;565         var checkstate = "-1"; //-1不选择,0部分选择,1全部选择566         var chkAll = false;567         if (checkbox) {568             var chkCls = ‘tree_chk_uncheck‘;569             chkBoxDiv = "<div class=‘chk_ioc tree_ioc_item tree_chk_ioc " + chkCls + "‘></div>";570             if (typeof nodef.checked == ‘boolean‘)571                 chkAll = nodef.checked;572         }573         var id = nodef[idField];574         var text = nodef[textField];575         var headHtml = "<div treedeep=‘" + controlData.treeDeep + "‘ isclose=‘" + closed + "‘ isfirstf=‘" + controlData.isFirstf + "‘ islastf=‘" + controlData.isLastf + "‘ isrootlast=‘" + controlData.isRootLast + "‘ isrootfirst=‘" + controlData.isRootFirst + "‘ path=‘" + controlData.path + "‘ checkstate=‘" + checkstate + "‘ checkedcount=‘0‘ childcount=‘" + treeJson.length + "‘ isleaf=‘false‘ pid=‘" + nodef.pid + "‘ islast=‘" + controlData.isLast + "‘ isfirst=‘" + controlData.isFirst + "‘ isroot=‘" + controlData.isRoot + "‘ treedeep=‘" + controlData.treeDeep + "‘ id=‘" + id + "‘ class=\"tree_ioc_wrap\">" + fixLineDiv + iconDiv + chkBoxDiv + "<div class=‘tree_li_text‘>" + text + "</div></div>";576         var headObj = $(headHtml).appendTo(target);577         if (typeof treeOpts.onClick == ‘function‘) {578             headObj.bind(‘click‘, function () {579                 var data = http://www.mamicode.com/getNodeByPath(treeDataObj,$(this).attr("path").split("_"));580                 treeOpts.onClick(data);581             });582         }  583         if (checkbox) {584             headObj.children(".chk_ioc").bind(‘click‘, chkClick);585         }586         headObj.children(".node_ioc").bind(‘click‘, nodeClick);587         var ul = $("<ul  style=‘" + hideCls + "‘></ul>").appendTo(target);588         var chkCount = 0;589         $.each(treeJson, function (i, node) {590             var children = node.children;591             node.pid = id;592             node.idx = i;593             var cdata = http://www.mamicode.com/{ //控制参数594                 isRoot: false,595                 isFirst: false,596                 isLast: false,597                 path: controlData.path + "_" + i,598                 isLeaf: false,599                 isLastf: false,600                 isFirstf: false,601                 treeDeep: controlData.treeDeep + 1,602                 isRootFirst: controlData.isRootFirst,603                 isRootLast: controlData.isRootLast604             };605             if (checkbox) {606                 if (chkAll)607                     node.checked = true;608                 if (node.checked)609                     chkCount++;610             }611             if (controlData.isLast)612                 cdata.isLastf = true;613             if (controlData.isFirst)614                 cdata.isFirstf = true;615             if (i == treeJson.length - 1)616                 cdata.isLast = true;617             if (i == 0)618                 cdata.isFirst = true;619             if (typeof children != ‘undefined‘ && $.isArray(children)) {620                 var li = $("<li class=\"tree_li\"></li>").appendTo(ul);621                 if (children.length == 0)622                     node.closed = true;623                 headObj = loopCreateTree(node, li, cdata);624             } else {625                 headObj = createLeafNode(node, ul, cdata);626             }627         });628         if (chkCount == treeJson.length)629             nodef.checked = true;630         else631             nodef.checked = false;632         return headObj;633     };634     /**********私有方法结束*******************/635     var methods = {636         init: function (options) {637             if ($.isArray(options)) {638                 options = {639                     data: options640                 };641             }642             return this.each(function () {643                 var $this = $(this);644                 var settings = $this.data(‘settings‘);645                 if (typeof (settings) == ‘undefined‘) {646                     settings = $.extend({}, $.fn.tree.defaults, options);647                     $this.data(‘settings‘, settings);648                 } else {649                     settings = $.extend({}, settings, options);650                 }651                 //创建ui布局652                 if (settings.url != ‘‘) {//远程请求数据653                     onl oadSuccess = settings.onLoadSuccess;654                     url = settings.url;655                     queryData(‘‘,$this, function (data) {656                         settings.data =http://www.mamicode.com/ data;657                         renderHtml($this);658                     });659                 } else {660                     renderHtml($this);661                 }               662                 if ($.myui.isDebug) {663                     $.myui.log("jQuery.tree init finish......");664                 }665             });666         },667         destroy: function (options) {668             return $(this).each(function () {669                 var $this = $(this);670                 $this.removeData(‘settings‘);671             });672         },673         /****674         *@params path 节点路径,path为空时则获取整个树所有checked状态的节点675         &@return 节点数组676         *****/677         getCheckNodes: function (path) {678             var pathArr = path.split(‘_‘);679             return getCheckedNodeByPath(treeDataObj, pathArr);680         }681     };682     /********************683     *组件的构造函数684     *********************/685     $.fn.tree = function () {686         var method = arguments[0];687         if (methods[method]) {688             method = methods[method];689             arguments = Array.prototype.slice.call(arguments, 1);690         } else if (typeof (method) == ‘object‘ || !method) {691             if ($.myui.isDebug) {692                 $.myui.log("jQuery.tree init.....");693             }694             method = methods.init;695         } else {696             $.error(‘Method ‘ + method + ‘ does not exist on jQuery.tree‘);697             return this;698         }699         return method.apply(this, arguments);700     };701     /********************702     *组件的默认配置值703     *********************/704     $.fn.tree.defaults = {705         textField: ‘text‘,//菜单名称字段,默认为text706         idField: ‘id‘,//菜单id字段,默认为id707         url: ‘‘,//远程加载数据地址708         lazy:false,//延时加载,当设置为true时,点击节点展开时,如果子元素为空则根据节点id发起请求加载子节点集合709         data: null,//树json数据    710         isPlain: false,//true 为简单无图标样式711         checkbox: false,//是否需要选择框712         animate: true,//是否需要动画713         onl oadSuccess: null,//加载成功714         onClick: null,//点击事件 715         isDrag: false,//是否可以拖拽调整节点716         onPreDrag: null,//拖拽前 未实现717         onDrag: null,//拖拽释放后未实现,718         contextMenu: false //右键菜单未实现719     };720 })(jQuery);