zoukankan      html  css  js  c++  java
  • 我的开源框架之树控件

    需求:

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

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

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

    4.支持复选框

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

    6.支持节点点击事件

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

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

    实现图例

    客户代码

     1 <body>
     2     <div id="Container" style="padding:10px; margin:0 auto;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 = [{
    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: data
    64                 lazy:true,                
    65                 url: 'testServer/jsonQuestTest.ashx?flag=tree',
    66                 onLoadSuccess: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 onLoadSuccess = null;//加载成功
     12     function renderHtml(target) {
     13         target.addClass('tree');
     14         treeOpts = target.data('settings');       
     15         if (treeOpts.data == 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={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 = {//控制参数
     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 onLoadSuccess === 'function') {
     95                     onLoadSuccess(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         else
    247             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                 else
    339                     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                     else
    348                         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                 else
    373                     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,采用settimeout
    391                         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 = {
    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         else
    421             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 = 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 = 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 = { //控制参数
    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.isRootLast
    604             };
    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         else
    631             nodef.checked = false;
    632         return headObj;
    633     };
    634     /**********私有方法结束*******************/
    635     var methods = {
    636         init: function (options) {
    637             if ($.isArray(options)) {
    638                 options = {
    639                     data: options
    640                 };
    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                     onLoadSuccess = settings.onLoadSuccess;
    654                     url = settings.url;
    655                     queryData('',$this, function (data) {
    656                         settings.data = 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',//菜单名称字段,默认为text
    706         idField: 'id',//菜单id字段,默认为id
    707         url: '',//远程加载数据地址
    708         lazy:false,//延时加载,当设置为true时,点击节点展开时,如果子元素为空则根据节点id发起请求加载子节点集合
    709         data: null,//树json数据    
    710         isPlain: false,//true 为简单无图标样式
    711         checkbox: false,//是否需要选择框
    712         animate: true,//是否需要动画
    713         onLoadSuccess: null,//加载成功
    714         onClick: null,//点击事件 
    715         isDrag: false,//是否可以拖拽调整节点
    716         onPreDrag: null,//拖拽前 未实现
    717         onDrag: null,//拖拽释放后未实现,
    718         contextMenu: false //右键菜单未实现
    719     };
    720 })(jQuery);
  • 相关阅读:
    haproxy 2.5 发布
    cube.js sql 支持简单说明
    基于graalvm 开发一个cube.js jdbc driver 的思路
    apache kyuubi Frontend 支持mysql 协议
    oceanbase 资源池删除说明
    基于obd 的oceanbase 扩容说明
    jfilter一个方便的spring rest 响应过滤扩展
    cube.js schema 定义多datasource 说明
    typescript 编写自定义定义文件
    meow 辅助开发cli 应用的工具
  • 原文地址:https://www.cnblogs.com/hjwen/p/3886918.html
Copyright © 2011-2022 走看看