| /** | 
|  * @Name: 基于layui的tree重写 | 
|  * @Author: 李祥 | 
|  * @License:MIT | 
|  * 最近修改时间: 2019/05/20 | 
|  * https://layuiextend.hsianglee.cn/eletree/ | 
|  */ | 
|   | 
| layui.define(["jquery", "laytpl"], function (exports) { | 
|     var $ = layui.jquery; | 
|     var laytpl = layui.laytpl; | 
|     var hint = layui.hint(); | 
|   | 
|     var MOD_NAME = "eleTree"; | 
|   | 
|     //外部接口 | 
|     var eleTree = { | 
|         //事件监听 | 
|         on: function (events, callback) { | 
|             return layui.onevent.call(this, MOD_NAME, events, callback); | 
|         }, | 
|         render: function (options) { | 
|             var inst = new Class(options); | 
|             return thisTree.call(inst); | 
|         } | 
|     } | 
|   | 
|     var thisTree = function () { | 
|         var _self = this; | 
|         var options = _self.config; | 
|   | 
|         // 暴漏外面的方法 | 
|         return { | 
|             // 接收两个参数,1. 节点 key 2. 节点数据的数组 | 
|             updateKeyChildren: function (key, data) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.updateKeyChildren.call(_self, key, data); | 
|             }, | 
|             updateKeySelf: function (key, data) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.updateKeySelf.call(_self, key, data); | 
|             }, | 
|             remove: function (key) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.remove.call(_self, key); | 
|             }, | 
|             append: function (key, data) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.append.call(_self, key, data); | 
|             }, | 
|             insertBefore: function (key, data) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.insertBefore.call(_self, key, data); | 
|             }, | 
|             insertAfter: function (key, data) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.insertAfter.call(_self, key, data); | 
|             }, | 
|             // 接收两个 boolean 类型的参数,1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false | 
|             getChecked: function (leafOnly, includeHalfChecked) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.getChecked.call(_self, leafOnly, includeHalfChecked); | 
|             }, | 
|             // 接收勾选节点数据的数组 | 
|             setChecked: function (data, isReset) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.setChecked.call(_self, data, isReset); | 
|             }, | 
|             // 取消选中 | 
|             unCheckNodes: function () { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.unCheckNodes.call(_self); | 
|             }, | 
|             unCheckArrNodes: function (data) { | 
|                 if (options.data.length === 0) return; | 
|                 return _self.unCheckArrNodes.call(_self, data); | 
|             }, | 
|             expandAll: function () { | 
|                 options.elem.children(".eleTree-node").children(".eleTree-node-group").empty(); | 
|                 _self.expandAll.call(_self, options.data, [], 1, true); | 
|                 _self.unCheckNodes(true); | 
|                 _self.defaultChecked(); | 
|                 _self.checkboxInit(); | 
|             }, | 
|             unExpandAll: function () { | 
|                 return _self.unExpandAll.call(_self); | 
|             }, | 
|             reload: function (options) { | 
|                 return _self.reload.call(_self, options); | 
|             }, | 
|             search: function (value) { | 
|                 return _self.search.call(_self, value); | 
|             } | 
|         } | 
|     } | 
|   | 
|     // 模板渲染 | 
|     var TPL_ELEM = function (options, floor, parentStatus) { | 
|         return [ | 
|             '{{# for(var i=0;i<d.length;i++){ }}', | 
|             '<div class="eleTree-node {{# if(d[i].visible===false){ }}eleTree-search-hide{{# } }}" data-' + options.request.key + '="{{d[i]["' + options.request.key + '"]}}" eletree-floor="' + floor + '" style="display: none;">', | 
|             '<div class="eleTree-node-content" type="{{d[i]["' + options.request.data + '"].type}}" style="padding-left: ' + (options.indent * floor) + 'px;">', | 
|             '<span class="eleTree-node-content-icon">', | 
|             '<i class="layui-icon layui-icon-triangle-r ', | 
|             function () { | 
|                 if (options.lazy) { | 
|                     var str = [ | 
|                         '{{# if(!d[i]["' + options.request.isLeaf + '"]){ }}', | 
|                         'lazy-icon" ></i>', | 
|                         '{{# }else{ }}', | 
|                         'leaf-icon" style="color: transparent;" ></i>', | 
|                         '{{# } }}' | 
|                     ].join(""); | 
|                     return str; | 
|                 } | 
|                 return ['{{# if(!d[i]["' + options.request.children + '"] || d[i]["' + options.request.children + '"].length===0){ }}', | 
|                     'leaf-icon" style="color: transparent;"', | 
|                     '{{# } }}', | 
|                     '"></i>' | 
|                 ].join(""); | 
|             }(), | 
|             '</span>', | 
|             function () { | 
|                 if (options.showCheckbox) { | 
|                     var status = ""; | 
|                     if (parentStatus === "1") { | 
|                         status = '"1" checked'; | 
|                     } else if (parentStatus === "2") { | 
|                         status = '"2"'; | 
|                     } else { | 
|                         status = '"0"'; | 
|                     } | 
|                     return [ | 
|                         '{{# if(d[i]["' + options.request.checked + '"]) { }}', | 
|                         '<input type="checkbox" name="eleTree-node" lay-ignore eleTree-status="1" checked data-checked class="layui-hide eleTree-hideen ', | 
|                         '{{# }else{ }}', | 
|                         '<input type="checkbox" name="eleTree-node" lay-ignore eleTree-status=' + status + ' class="layui-hide eleTree-hideen ', | 
|                         '{{# } }}', | 
|   | 
|                         '{{# if(d[i]["' + options.request.disabled + '"]) { }}', | 
|                         'eleTree-disabled', | 
|                         '{{# } }}', | 
|                         '" />' | 
|                     ].join(""); | 
|                 } | 
|                 return '' | 
|             }(), | 
|             '<span class="eleTree-node-content-label">{{d[i]["' + options.request.name + '"]}}</span>', | 
|             '</div>', | 
|             '<div class="eleTree-node-group">', | 
|             '</div>', | 
|             '</div>', | 
|             '{{# } }}' | 
|         ].join(""); | 
|     } | 
|   | 
|     var TPL_NoText = function () { | 
|         return '<h3 class="eleTree-noText" style="text-align: center;height: 30px;line-height: 30px;color: #888;">{{d.emptText}}</h3>'; | 
|     } | 
|   | 
|     var Class = function (options) { | 
|         options.response = $.extend({}, this.config.response, options.response); | 
|         options.request = $.extend({}, this.config.request, options.request); | 
|         this.config = $.extend({}, this.config, options); | 
|         this.prevClickEle = null; | 
|         this.nameIndex = 1; | 
|         this.render(); | 
|     }; | 
|   | 
|     Class.prototype = { | 
|         constructor: Class, | 
|         config: { | 
|             elem: "", | 
|             data: [], | 
|             emptText: "暂无数据",        // 内容为空的时候展示的文本 | 
|             renderAfterExpand: true,    // 是否在第一次展开某个树节点后才渲染其子节点 | 
|             highlightCurrent: false,    // 是否高亮当前选中节点,默认值是 false。 | 
|             defaultExpandAll: false,    // 是否默认展开所有节点 | 
|             expandOnClickNode: true,    // 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。 | 
|             checkOnClickNode: false,    // 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。 | 
|             defaultExpandedKeys: [],    // 默认展开的节点的 key 的数组 | 
|             autoExpandParent: true,     // 展开子节点的时候是否自动展开父节点 | 
|             showCheckbox: false,        // 节点是否可被选择 | 
|             checkStrictly: false,       // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false | 
|             defaultCheckedKeys: [],     // 默认勾选的节点的 key 的数组 | 
|             accordion: false,           // 是否每次只打开一个同级树节点展开(手风琴效果) | 
|             indent: 16,                 // 相邻级节点间的水平缩进,单位为像素 | 
|             lazy: false,                // 是否懒加载子节点,需与 load 方法结合使用 | 
|             load: function () { | 
|             },        // 加载子树数据的方法,仅当 lazy 属性为true 时生效 | 
|             draggable: false,           // 是否开启拖拽节点功能 | 
|             contextmenuList: [],        // 启用右键菜单,支持的操作有:"copy","add","edit","remove" | 
|             searchNodeMethod: null,     // 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏 | 
|   | 
|             method: "get", | 
|             url: "", | 
|             contentType: "", | 
|             headers: {}, | 
|             done: null, | 
|   | 
|             response: { | 
|                 statusName: "code", | 
|                 statusCode: 0, | 
|                 dataName: "data" | 
|             }, | 
|             request: { | 
|                 name: "label", | 
|                 key: "id", | 
|                 children: "children", | 
|                 disabled: "disabled", | 
|                 checked: "checked", | 
|                 isLeaf: "isLeaf" | 
|             } | 
|         }, | 
|         render: function () { | 
|             if (this.config.indent > 30) { | 
|                 this.config.indent = 30; | 
|             } else if (this.config.indent < 10) { | 
|                 this.config.indent = 10; | 
|             } | 
|             var options = this.config; | 
|             options.where = options.where || {}; | 
|             if (!options.elem) return hint.error("缺少elem参数"); | 
|             options.elem = typeof options.elem === "string" ? $(options.elem) : options.elem; | 
|             this.filter = options.elem.attr("lay-filter"); | 
|             // load加载框 | 
|             options.elem.append('<div class="eleTree-loadData"><i class="layui-icon layui-icon-loading layui-icon layui-anim layui-anim-rotate layui-anim-loop"></i></div>') | 
|   | 
|             // 判断加载方式 | 
|             if (options.data.length === 0) { | 
|                 this.ajaxGetData(); | 
|             } else { | 
|                 this.renderData(); | 
|             } | 
|         }, | 
|         renderData: function () { | 
|             var options = this.config; | 
|             $(this.config.elem).off();  // 取消事件绑定,防止多次绑定事件 | 
|             // 渲染第一层 | 
|             laytpl(TPL_ELEM(options, 0)).render(options.data, function (string) { | 
|                 options.elem.html(string).children().show(); | 
|             }); | 
|             // 懒加载 > 展开所有 > 初始展开项 > 初始渲染所有子节点 > 初始选中项 > 每次点击只渲染当前层(默认) | 
|             // 判断所有dom是否全部加载 | 
|             if (!options.lazy) { | 
|                 if (!options.renderAfterExpand || options.defaultExpandAll || options.defaultExpandedKeys.length > 0 || options.defaultCheckedKeys.length > 0) { | 
|                     this.expandAll(options.data, [], 1); | 
|                 } | 
|             } | 
|   | 
|             this.eleTreeEvent(); | 
|             this.checkboxRender(); | 
|             this.checkboxEvent(); | 
|             this.defaultChecked(); | 
|             this.nodeEvent(); | 
|             this.rightClickMenu(); | 
|             if (!options.checkStrictly) { | 
|                 this.checkboxInit(); | 
|             } | 
|         }, | 
|         ajaxGetData: function () { | 
|             var options = this.config; | 
|             var _self = this; | 
|             if (!options.url) { | 
|                 laytpl(TPL_NoText()).render(options, function (string) { | 
|                     options.elem.html(string); | 
|                 }); | 
|                 return; | 
|             } | 
|             var data = $.extend({}, options.where); | 
|             if (options.contentType && options.contentType.indexOf("application/json") == 0) { //提交 json 格式 | 
|                 data = JSON.stringify(data); | 
|             } | 
|   | 
|             $.ajax({ | 
|                 type: options.method || 'get' | 
|                 , url: options.url | 
|                 , contentType: options.contentType | 
|                 , data: data | 
|                 , dataType: 'json' | 
|                 , headers: options.headers || {} | 
|                 , success: function (res) { | 
|                     if (res[options.response.statusName] != options.response.statusCode || !res[options.response.dataName]) { | 
|                         hint.error("请检查数据格式是否符合规范"); | 
|                         typeof options.done === 'function' && options.done(res); | 
|                         return; | 
|                     } | 
|                     options.data = res[options.response.dataName]; | 
|                     _self.renderData(); | 
|                     typeof options.done === 'function' && options.done(res); | 
|                 } | 
|             }); | 
|         }, | 
|         reload: function (options) { | 
|             var _self = this; | 
|             if (this.config.data && this.config.data.constructor === Array) this.config.data = []; | 
|             this.config = $.extend({}, this.config, options); | 
|             // $(this.config.elem).off();  // 取消事件绑定,防止多次绑定事件 | 
|             // reload记录选中的数据 | 
|             // this.getChecked().forEach(function(val) { | 
|             //     if($.inArray(val.key,this.config.defaultCheckedKeys)===-1){ | 
|             //         this.config.defaultCheckedKeys.push(val.key); | 
|             //     } | 
|             // },this); | 
|             return eleTree.render(this.config) | 
|         }, | 
|         // 下拉 | 
|         eleTreeEvent: function () { | 
|             var _self = this; | 
|             var options = this.config; | 
|             // 下拉 | 
|             var expandOnClickNode = options.expandOnClickNode ? ".eleTree-node-content" : ".eleTree-node-content>.eleTree-node-content-icon"; | 
|             options.elem.on("click", expandOnClickNode, function (e) { | 
|                 e.stopPropagation(); | 
|                 var eleTreeNodeContent = $(this).parent(".eleTree-node").length === 0 ? $(this).parent(".eleTree-node-content") : $(this); | 
|                 var eleNode = eleTreeNodeContent.parent(".eleTree-node"); | 
|                 var sibNode = eleTreeNodeContent.siblings(".eleTree-node-group"); | 
|                 var el = eleTreeNodeContent.children(".eleTree-node-content-icon").children(".layui-icon"); | 
|   | 
|                 // 添加active背景 | 
|                 if (_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active"); | 
|                 if (options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active"); | 
|                 _self.prevClickEle = eleTreeNodeContent; | 
|   | 
|   | 
|                 if (el.hasClass("icon-rotate")) { | 
|                     // 合并 | 
|                     sibNode.children(".eleTree-node:not(.eleTree-search-hide)").hide("fast"); | 
|                     el.removeClass("icon-rotate"); | 
|                     return; | 
|                 } | 
|   | 
|                 if (sibNode.children(".eleTree-node").length === 0) { | 
|                     var floor = Number(eleNode.attr("eletree-floor")) + 1; | 
|   | 
|                     // 选择祖父 | 
|                     var selectParentsFn = function () { | 
|                         if (!options.checkStrictly) { | 
|                             var eleNode1 = sibNode.children(".eleTree-node").eq(0); | 
|                             if (eleNode1.length !== 0) { | 
|                                 var siblingNode1 = eleNode1.siblings(".eleTree-node"); | 
|                                 var item1 = eleNode1.children(".eleTree-node-content").children(".eleTree-hideen").get(0); | 
|                                 _self.selectParents(item1, eleNode1, siblingNode1); | 
|                             } | 
|                         } | 
|                     } | 
|   | 
|                     var data = _self.reInitData(eleNode); | 
|                     var d = data.currentData; | 
|                     // 是否懒加载 | 
|                     if (options.lazy && el.hasClass("lazy-icon")) { | 
|                         el.removeClass("layui-icon-triangle-r").addClass("layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"); | 
|                         options.load(d, function (getData) { | 
|                             // 如果原来有数据则合并,没有则赋值 | 
|                             if (d[options.request.children]) { | 
|                                 d[options.request.children] = d[options.request.children].concat(getData); | 
|                             } else { | 
|                                 d[options.request.children] = getData; | 
|                             } | 
|                             var eletreeStatus = eleTreeNodeContent.children("input.eleTree-hideen").attr("eletree-status"); | 
|                             if (d[options.request.children] && d[options.request.children].length > 0) { | 
|                                 // 只渲染获取到的数据 | 
|                                 laytpl(TPL_ELEM(options, floor, eletreeStatus)).render(getData, function (string) { | 
|                                     sibNode.append(string).children().show("fast"); | 
|                                 }); | 
|                             } else { | 
|                                 el.css("color", "transparent").addClass("leaf-icon"); | 
|                             } | 
|                             el.removeClass("lazy-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop").addClass("layui-icon-triangle-r icon-rotate"); | 
|   | 
|                             // 懒加载子元素选择祖父(待写) | 
|                             selectParentsFn(); | 
|                             _self.checkboxRender(); | 
|                         }) | 
|                     } else { | 
|                         var eletreeStatus = eleTreeNodeContent.children("input.eleTree-hideen").attr("eletree-status"); | 
|                         d[options.request.children] && d[options.request.children].length > 0 && laytpl(TPL_ELEM(options, floor, eletreeStatus)).render(d[options.request.children], function (string) { | 
|                             sibNode.append(string); | 
|                         }); | 
|                         // 选择祖父 | 
|                         selectParentsFn(); | 
|                         _self.checkboxRender(); | 
|                     } | 
|                 } | 
|                 // 显示隐藏没有搜索类的 | 
|                 sibNode.children(".eleTree-node:not(.eleTree-search-hide)").show("fast"); | 
|                 el.addClass("icon-rotate"); | 
|                 // 手风琴效果 | 
|                 if (options.accordion) { | 
|                     var node = eleTreeNodeContent.parent(".eleTree-node").siblings(".eleTree-node"); | 
|                     node.children(".eleTree-node-group").children(".eleTree-node:not(.eleTree-search-hide)").hide("fast"); | 
|                     node.children(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").removeClass("icon-rotate"); | 
|                 } | 
|             }) | 
|         }, | 
|         // checkbox选中 | 
|         checkboxEvent: function () { | 
|             var options = this.config; | 
|             var _self = this; | 
|             var checkOnClickNode = options.checkOnClickNode ? ".eleTree-node-content" : ".eleTree-checkbox"; | 
|             // input添加属性eleTree-status:即input的三种状态,"0":未选中,"1":选中,"2":子孙部分选中 | 
|             options.elem.on("click", checkOnClickNode, function (e) { | 
|                 e.stopPropagation(); | 
|                 var eleTreeNodeContent = $(this).parent(".eleTree-node").length === 0 ? $(this).parent(".eleTree-node-content") : $(this); | 
|                 var checkbox = eleTreeNodeContent.children(".eleTree-checkbox"); | 
|                 if (checkbox.hasClass("eleTree-checkbox-disabled")) return; | 
|                 // 获取点击所在数据 | 
|                 var node = eleTreeNodeContent.parent(".eleTree-node"); | 
|                 // var d=_self.reInitData(node).currentData; | 
|                 // 实际的input | 
|                 var inp = checkbox.siblings(".eleTree-hideen").get(0); | 
|                 var childNode = eleTreeNodeContent.siblings(".eleTree-node-group").find("input[name='eleTree-node']"); | 
|   | 
|                 // 添加active背景 | 
|                 if (_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active"); | 
|                 if (options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active"); | 
|                 _self.prevClickEle = eleTreeNodeContent; | 
|   | 
|                 if (!inp) return; | 
|   | 
|                 if (inp.checked) { | 
|                     // 反选自身 | 
|                     $(inp).prop("checked", false).attr("eleTree-status", "0"); | 
|                     // 点击祖父层选中子孙层 | 
|                     if (!options.checkStrictly) { | 
|                         childNode.prop("checked", false); | 
|                         childNode.attr("eleTree-status", "0"); | 
|                     } | 
|   | 
|                 } else { | 
|                     // 反选自身 | 
|                     $(inp).prop("checked", true).attr("eleTree-status", "1"); | 
|                     // 点击祖父层选中子孙层 | 
|                     if (!options.checkStrictly) { | 
|                         childNode.prop("checked", true).attr("eleTree-status", "1"); | 
|                     } | 
|                 } | 
|   | 
|                 var eleNode = eleTreeNodeContent.parent(".eleTree-node"); | 
|                 // 点击子孙层选中祖父层(递归) | 
|                 if (!options.checkStrictly) { | 
|                     var siblingNode = eleNode.siblings(".eleTree-node"); | 
|                     // 点击子孙层选中祖父层(递归) | 
|                     _self.selectParents(inp, eleNode, siblingNode); | 
|                 } | 
|   | 
|                 _self.checkboxRender(); | 
|   | 
|                 layui.event.call(inp, MOD_NAME, 'nodeChecked(' + _self.filter + ')', { | 
|                     node: eleNode, | 
|                     data: _self.reInitData(eleNode), | 
|                     isChecked: inp.checked | 
|                 }); | 
|             }) | 
|         }, | 
|         // 对后台数据有 checked:true 的默认选中项渲染父子层 | 
|         checkboxInit: function () { | 
|             var options = this.config; | 
|             var _self = this; | 
|             options.elem.find("input[data-checked]").each(function (index, item) { | 
|                 var checkboxEl = $(item).siblings(".eleTree-checkbox"); | 
|                 var childNode = checkboxEl.parent(".eleTree-node-content").siblings(".eleTree-node-group").find("input[name='eleTree-node']"); | 
|                 // 选择当前 | 
|                 $(item).prop("checked", "checked").attr("eleTree-status", "1"); | 
|                 checkboxEl.addClass("eleTree-checkbox-checked"); | 
|                 checkboxEl.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line"); | 
|                 if (options.checkStrictly) return; | 
|                 // 选择子孙 | 
|                 childNode.prop("checked", "checked").attr("eleTree-status", "1"); | 
|                 childNode.siblings(".eleTree-checkbox").addClass("eleTree-checkbox-checked"); | 
|                 childNode.siblings(".eleTree-checkbox").children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line"); | 
|   | 
|                 // 选择祖父 | 
|                 var eleNode = checkboxEl.parent(".eleTree-node-content").parent(".eleTree-node"); | 
|                 var siblingNode = eleNode.siblings(".eleTree-node"); | 
|                 _self.selectParents(item, eleNode, siblingNode); | 
|             }) | 
|             _self.checkboxRender(); | 
|         }, | 
|         // 通过子元素选中祖父元素 | 
|         selectParents: function (inp, eleNode, siblingNode) { | 
|             // inp: 实际input(dom元素) | 
|             // eleNode: input父层类(.eleTree-node) | 
|             // siblingNode: 父层同级兄弟 | 
|             while (Number(eleNode.attr("eletree-floor")) !== 0) { | 
|                 // 同级input状态存入数组 | 
|                 var arr = []; | 
|                 arr.push($(inp).attr("eleTree-status")); | 
|                 siblingNode.each(function (index, item) { | 
|                     var siblingIsChecked = $(item).children(".eleTree-node-content").children("input[name='eleTree-node']").attr("eleTree-status"); | 
|                     arr.push(siblingIsChecked); | 
|                 }) | 
|                 // 父元素的实际input | 
|                 var parentInput = eleNode.parent(".eleTree-node-group").siblings(".eleTree-node-content").children("input[name='eleTree-node']"); | 
|                 // 父元素的checkbox替代 | 
|                 var parentCheckbox = parentInput.siblings(".eleTree-checkbox"); | 
|                 // 子都选中则选中父 | 
|                 if (arr.every(function (val) { | 
|                     return val === "1"; | 
|                 })) { | 
|                     parentInput.prop("checked", true).attr("eleTree-status", "1"); | 
|                 } | 
|                 // 子有一个未选中则checkbox第三种状态 | 
|                 if (arr.some(function (val) { | 
|                     return val === "0" || val === "2"; | 
|                 })) { | 
|                     parentInput.attr("eleTree-status", "2"); | 
|                 } | 
|                 // 子全部未选中则取消父选中(并且取消第三种状态) | 
|                 if (arr.every(function (val) { | 
|                     return val === "0"; | 
|                 })) { | 
|                     parentInput.prop("checked", false); | 
|                     parentInput.attr("eleTree-status", "0"); | 
|                 } | 
|   | 
|                 var parentNode = eleNode.parents("[eletree-floor='" + (Number(eleNode.attr("eletree-floor")) - 1) + "']"); | 
|                 var parentCheckbox = parentNode.children(".eleTree-node-content").children("input[name='eleTree-node']").get(0); | 
|                 var parentSiblingNode = parentNode.siblings(".eleTree-node"); | 
|                 eleNode = parentNode; | 
|                 inp = parentCheckbox; | 
|                 siblingNode = parentSiblingNode; | 
|             } | 
|         }, | 
|         // 初始展开所有 | 
|         expandAll: function (data, arr, floor, isMethodsExpandAll) { | 
|             var options = this.config; | 
|             var _self = this; | 
|             data.forEach(function (val, index) { | 
|                 arr.push(index); | 
|                 if (val[options.request.children] && val[options.request.children].length > 0) { | 
|                     var el = options.elem.children(".eleTree-node").eq(arr[0]).children(".eleTree-node-group"); | 
|                     for (var i = 1; i < arr.length; i++) { | 
|                         el = el.children(".eleTree-node").eq(arr[i]).children(".eleTree-node-group"); | 
|                     } | 
|                     laytpl(TPL_ELEM(options, floor)).render(val[options.request.children], function (string) { | 
|                         el.append(string); | 
|                         // 判断是否展开所有 | 
|                         if (options.defaultExpandAll || isMethodsExpandAll) { | 
|                             el.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate"); | 
|                             el.children().show(); | 
|                         } else if (options.defaultExpandedKeys.length > 0) { | 
|                             // 继续展开祖父层 | 
|                             var f = function (eleP) { | 
|                                 if (options.autoExpandParent) { | 
|                                     eleP.parents(".eleTree-node").each(function (i, item) { | 
|                                         if ($(item).data(options.request.key)) { | 
|                                             $(item).children(".eleTree-node-group").siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate"); | 
|                                             $(item).children(".eleTree-node-group").children().show(); | 
|                                         } | 
|                                     }) | 
|                                 } | 
|                             } | 
|                             // 展开指定id项 | 
|                             var id = el.parent(".eleTree-node").data(options.request.key); | 
|                             if ($.inArray(id, options.defaultExpandedKeys) !== -1) { | 
|                                 // 直接展开子节点 | 
|                                 el.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate"); | 
|                                 el.children().show(); | 
|                                 // 展开子项是否继续展开祖父项 | 
|                                 f(el.parent(".eleTree-node[data-" + options.request.key + "]")); | 
|                             } else { | 
|                                 // 如当前节点的子节点有展开项,则展开当前子节点的祖父层 | 
|                                 el.children(".eleTree-node").each(function (index, item) { | 
|                                     var id = $(item).data(options.request.key); | 
|                                     if ($.inArray(id, options.defaultExpandedKeys) !== -1) { | 
|                                         f($(item)); | 
|                                         return false; | 
|                                     } | 
|                                 }) | 
|                             } | 
|                         } | 
|                     }); | 
|                     floor++; | 
|                     _self.expandAll(val[options.request.children], arr, floor, isMethodsExpandAll); | 
|                     floor--; | 
|                 } | 
|                 // 重置数组索引 | 
|                 arr.pop(); | 
|             }) | 
|   | 
|   | 
|         }, | 
|         // 选中单个节点 | 
|         checkedOneNode: function (nodeContent) { | 
|             var options = this.config; | 
|             var inp = nodeContent.children("input.eleTree-hideen").get(0); | 
|             $(inp).prop("checked", true).attr("eleTree-status", "1"); | 
|   | 
|             if (options.checkStrictly) return; | 
|   | 
|             // 点击祖父层选中子孙层 | 
|             var childNode = nodeContent.siblings(".eleTree-node-group").find("input[name='eleTree-node']"); | 
|             childNode.prop("checked", true).attr("eleTree-status", "1"); | 
|   | 
|             var eleNode = nodeContent.parent(".eleTree-node"); | 
|             var siblingNode = eleNode.siblings(".eleTree-node"); | 
|             // 点击子孙层选中祖父层(递归) | 
|             this.selectParents(inp, eleNode, siblingNode); | 
|         }, | 
|         // 初始默认选中 | 
|         defaultChecked: function (dataChecked) { | 
|             var options = this.config; | 
|             var _self = this; | 
|             var arr = dataChecked || options.defaultCheckedKeys; | 
|             if (arr.length === 0) { | 
|                 return false; | 
|             } | 
|             arr.forEach(function (val, index) { | 
|                 var nodeContent = options.elem.find("[data-" + options.request.key + "='" + val + "']").children(".eleTree-node-content"); | 
|                 nodeContent.length > 0 && _self.checkedOneNode(nodeContent); | 
|             }) | 
|             this.checkboxInit(); | 
|         }, | 
|         // 自定义checkbox解析 | 
|         checkboxRender: function () { | 
|             var options = this.config; | 
|             options.elem.find(".eleTree-checkbox").remove(); | 
|             options.elem.find("input.eleTree-hideen[type=checkbox]").each(function (index, item) { | 
|                 if ($(item).hasClass("eleTree-disabled")) { | 
|                     $(item).after('<div class="eleTree-checkbox eleTree-checkbox-disabled"><i class="layui-icon"></i></div>'); | 
|                 } else { | 
|                     $(item).after('<div class="eleTree-checkbox"><i class="layui-icon"></i></div>'); | 
|                 } | 
|   | 
|                 var checkbox = $(item).siblings(".eleTree-checkbox"); | 
|                 if ($(item).attr("eletree-status") === "1") { | 
|                     checkbox.addClass("eleTree-checkbox-checked"); | 
|                     checkbox.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line"); | 
|                 } else if ($(item).attr("eletree-status") === "0") { | 
|                     checkbox.removeClass("eleTree-checkbox-checked"); | 
|                     checkbox.children("i").removeClass("layui-icon-ok eleTree-checkbox-line"); | 
|                 } else if ($(item).attr("eletree-status") === "2") { | 
|                     checkbox.addClass("eleTree-checkbox-checked"); | 
|                     checkbox.children("i").removeClass("layui-icon-ok").addClass("eleTree-checkbox-line"); | 
|                 } | 
|   | 
|             }) | 
|         }, | 
|         // 通过dom节点找对应数据 | 
|         reInitData: function (node) { | 
|             var options = this.config; | 
|             var i = node.index(); | 
|             var floor = Number(node.attr("eletree-floor")); | 
|             var arr = [];     // 节点对应的index | 
|             while (floor >= 0) { | 
|                 arr.push(i); | 
|                 floor = floor - 1; | 
|                 node = node.parents("[eletree-floor='" + floor + "']"); | 
|                 i = node.index(); | 
|             } | 
|             arr = arr.reverse(); | 
|             var oData = this.config.data; | 
|             // 当前节点的父节点数据 | 
|             var parentData = oData[arr[0]]; | 
|             // 当前节点的data数据 | 
|             var d = oData[arr[0]]; | 
|             for (var j = 1; j < arr.length; j++) { | 
|                 d = d[options.request.children] ? d[options.request.children][arr[j]] : d; | 
|             } | 
|             for (var k = 1; k < arr.length - 1; k++) { | 
|                 parentData = parentData[options.request.children] ? parentData[options.request.children][arr[k]] : parentData; | 
|             } | 
|   | 
|             return { | 
|                 currentData: d, | 
|                 parentData: { | 
|                     data: parentData, | 
|                     childIndex: arr[arr.length - 1] | 
|                 }, | 
|                 index: arr | 
|             } | 
|         }, | 
|         // 通过key查找数据 | 
|         keySearchToOpera: function (key, callback) { | 
|             var options = this.config; | 
|             var _self = this; | 
|             // 查找数据 | 
|             var fn = function (data) { | 
|                 var obj = { | 
|                     i: 0, | 
|                     len: data.length | 
|                 } | 
|                 for (; obj.i < obj.len; obj.i++) { | 
|                     if (data[obj.i][options.request.key] != key) { | 
|                         if (data[obj.i][options.request.children] && data[obj.i][options.request.children].length > 0) { | 
|                             fn(data[obj.i][options.request.children]); | 
|                         } | 
|                     } else { | 
|                         callback(data, obj); | 
|                     } | 
|                 } | 
|             } | 
|             fn(options.data); | 
|         }, | 
|         updateKeyChildren: function (key, data) { | 
|             var options = this.config; | 
|             var node = options.elem.find("[data-" + options.request.key + "='" + key + "']"); | 
|             var floor = Number(node.attr("eletree-floor")) + 1; | 
|             var _self = this; | 
|   | 
|             this.keySearchToOpera(key, function (d, obj) { | 
|                 // 数据更新 | 
|                 d[obj.i][options.request.children] = data; | 
|                 // dom更新 | 
|                 node.length !== 0 && laytpl(TPL_ELEM(options, floor)).render(data, function (string) { | 
|                     $(node).children(".eleTree-node-group").empty().append(string); | 
|                     options.defaultExpandAll && $(node).children(".eleTree-node-group").children().show(); | 
|                 }); | 
|                 _self.unCheckNodes(true); | 
|                 _self.defaultChecked(); | 
|             }); | 
|         }, | 
|         updateKeySelf: function (key, data) { | 
|             var options = this.config; | 
|             var node = options.elem.find("[data-" + options.request.key + "='" + key + "']").children(".eleTree-node-content"); | 
|             var floor = Number(node.attr("eletree-floor")) + 1; | 
|             data[options.request.name] && node.children(".eleTree-node-content-label").text(data[options.request.name]); | 
|             data[options.request.disabled] && node.children(".eleTree-hideen").addClass("eleTree-disabled") | 
|                 .siblings(".eleTree-checkbox").addClass("eleTree-checkbox-disabled"); | 
|             // 数据更新 | 
|             var getData = this.keySearchToOpera(key, function (d, obj) { | 
|                 data[options.request.key] = d[obj.i][options.request.key]; | 
|                 data[options.request.children] = d[obj.i][options.request.children]; | 
|                 d[obj.i] = $.extend({}, d[obj.i], data); | 
|             }); | 
|         }, | 
|         remove: function (key) { | 
|             var options = this.config; | 
|             var node = options.elem.find("[data-" + options.request.key + "='" + key + "']"); | 
|             var pElem = node.parent(".eleTree-node-group"); | 
|             // 数据删除 | 
|             this.keySearchToOpera(key, function (data, obj) { | 
|                 data.splice(obj.i, 1); | 
|                 obj.i--; | 
|                 obj.len--; | 
|   | 
|                 node.length !== 0 && options.elem.find("[data-" + options.request.key + "='" + key + "']").remove(); | 
|                 if (pElem.children(".eleTree-node").length === 0) { | 
|                     pElem.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").css("color", "transparent"); | 
|                 } | 
|             }); | 
|             this.unCheckNodes(true); | 
|             this.defaultChecked(); | 
|             this.checkboxInit(); | 
|         }, | 
|         append: function (key, data) { | 
|             var options = this.config; | 
|             // 如果不传key,则直接添加到根节点 | 
|             if (typeof key === "object" && key !== null) { | 
|                 data = key; | 
|                 key = null; | 
|             } | 
|             if (key === null || key === "") { | 
|                 options.data.push(data); | 
|                 laytpl(TPL_ELEM(options, 0, "0")).render([data], function (string) { | 
|                     $(options.elem).append(string); | 
|                     $(options.elem).children(".eleTree-node:last").show(); | 
|                 }); | 
|                 this.checkboxRender(); | 
|                 return; | 
|             } | 
|             // 传key则添加到子节点 | 
|             var node = options.elem.find("[data-" + options.request.key + "='" + key + "']"); | 
|             var floor = Number(node.attr("eletree-floor")) + 1; | 
|             // 数据更新 | 
|             this.keySearchToOpera(key, function (d, obj) { | 
|                 if (d[obj.i][options.request.children]) { | 
|                     d[obj.i][options.request.children].push(data); | 
|                 } else { | 
|                     d[obj.i][options.request.children] = [data]; | 
|                 } | 
|                 var arr = d[obj.i][options.request.children]; | 
|                 var icon = node.children(".eleTree-node-content").find(".eleTree-node-content-icon .layui-icon"); | 
|                 // 添加之后长度为1,则原来没有三角,添加三角 | 
|                 if (arr.length === 1) { | 
|                     icon.removeAttr("style"); | 
|                 } | 
|                 // 判断原来是否没有展开 | 
|                 if (!icon.hasClass("icon-rotate")) { | 
|                     var expandOnClickNode = options.expandOnClickNode ? node.children(".eleTree-node-content") : node.children(".eleTree-node-content").children(".eleTree-node-content-icon"); | 
|                     expandOnClickNode.trigger("click"); | 
|                 } | 
|                 // 判断节点是否已存在 | 
|                 var isExist = false; | 
|                 node.children(".eleTree-node-group").children(".eleTree-node").each(function (index, item) { | 
|                     if (data[options.request.key] == $(item).data(options.request.key)) { | 
|                         isExist = true; | 
|                     } | 
|                 }) | 
|                 if (!isExist) { | 
|                     var len = arr.length; | 
|                     var eletreeStatus = node.children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status"); | 
|                     eletreeStatus = eletreeStatus === "2" ? "0" : eletreeStatus; | 
|                     node.length !== 0 && laytpl(TPL_ELEM(options, floor, eletreeStatus)).render([arr[len - 1]], function (string) { | 
|                         node.children(".eleTree-node-group").append(string).children().show(); | 
|                     }); | 
|                 } | 
|   | 
|             }); | 
|             this.checkboxRender(); | 
|         }, | 
|         insertBefore: function (key, data) { | 
|             var options = this.config; | 
|             var node = options.elem.find("[data-" + options.request.key + "='" + key + "']"); | 
|             var floor = Number(node.attr("eletree-floor")); | 
|             // 数据更新 | 
|             this.keySearchToOpera(key, function (d, obj) { | 
|                 d.splice(obj.i, 0, data); | 
|                 obj.i++; | 
|                 obj.len++; | 
|                 var eletreeStatus = node.parent(".eleTree-node-group").length === 0 ? "0" : node.parent(".eleTree-node-group").parent(".eleTree-node") | 
|                     .children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status"); | 
|                 eletreeStatus = eletreeStatus === "2" ? "0" : eletreeStatus; | 
|                 node.length !== 0 && laytpl(TPL_ELEM(options, floor, eletreeStatus)).render([data], function (string) { | 
|                     node.before(string).prev(".eleTree-node").show(); | 
|                 }); | 
|             }); | 
|             this.checkboxRender(); | 
|         }, | 
|         insertAfter: function (key, data) { | 
|             var options = this.config; | 
|             var node = options.elem.find("[data-" + options.request.key + "='" + key + "']"); | 
|             var floor = Number(node.attr("eletree-floor")); | 
|             // 数据更新 | 
|             this.keySearchToOpera(key, function (d, obj) { | 
|                 d.splice(obj.i + 1, 0, data); | 
|                 obj.i++; | 
|                 obj.len++; | 
|                 var eletreeStatus = node.parent(".eleTree-node-group").length === 0 ? "0" : node.parent(".eleTree-node-group").parent(".eleTree-node") | 
|                     .children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status"); | 
|                 eletreeStatus = eletreeStatus === "2" ? "0" : eletreeStatus; | 
|                 node.length !== 0 && laytpl(TPL_ELEM(options, floor, eletreeStatus)).render([data], function (string) { | 
|                     $(node).after(string).next(".eleTree-node").show(); | 
|                 }); | 
|             }); | 
|             this.checkboxRender(); | 
|             // if(!options.lazy){ | 
|             //     if(!options.renderAfterExpand || options.defaultExpandAll || options.defaultExpandedKeys.length>0){ | 
|             //         this.expandAll(options.data,[],1); | 
|             //     } | 
|             // } | 
|         }, | 
|         getChecked: function (leafOnly, includeHalfChecked) { | 
|             var options = this.config | 
|                 , el | 
|                 , arr = []; | 
|             leafOnly = leafOnly || false; | 
|             includeHalfChecked = includeHalfChecked || false; | 
|             if (leafOnly) { | 
|                 el = options.elem.find(".layui-icon.leaf-icon").parent(".eleTree-node-content-icon") | 
|                     .siblings("input.eleTree-hideen[eletree-status='1']"); | 
|             } else if (includeHalfChecked) { | 
|                 el = options.elem.find("input.eleTree-hideen[eletree-status='1'],input.eleTree-hideen[eletree-status='2']"); | 
|             } else { | 
|                 el = options.elem.find("input.eleTree-hideen[eletree-status='1']"); | 
|             } | 
|             el.each(function (index, item) { | 
|                 var obj = {}; | 
|                 var id = $(item).parent(".eleTree-node-content").parent(".eleTree-node").data(options.request.key); | 
|                 var label = $(item).siblings(".eleTree-node-content-label").text(); | 
|                 obj[options.request.key] = id; | 
|                 obj[options.request.name] = label; | 
|                 obj.elem = item; | 
|                 obj.type = $(item).parent(".eleTree-node-content").attr('type'); | 
|                 obj.othis = $(item).siblings(".eleTree-checkbox").get(0); | 
|                 arr.push(obj); | 
|             }) | 
|             return arr; | 
|         }, | 
|         setChecked: function (arr, isReset) { | 
|             var options = this.config; | 
|             isReset = isReset || false; | 
|             if (isReset) { | 
|                 this.unCheckNodes(); | 
|                 options.defaultCheckedKeys = $.extend([], arr); | 
|             } else { | 
|                 this.unCheckNodes(true); | 
|                 arr.forEach(function (val) { | 
|                     if ($.inArray(val, options.defaultCheckedKeys) === -1) { | 
|                         options.defaultCheckedKeys.push(val); | 
|                     } | 
|                 }) | 
|             } | 
|             this.defaultChecked(); | 
|         }, | 
|         unCheckNodes: function (_internal) { | 
|             _internal = _internal || false;   // _internal: 是否内部调用 | 
|             var options = this.config; | 
|             options.elem.find("input.eleTree-hideen[eletree-status='1'],input.eleTree-hideen[eletree-status='2']").each(function (index, item) { | 
|                 $(item).attr("eletree-status", "0").prop("checked", false); | 
|                 // 如果外部的取消选中,则所有的记录全部取消 | 
|                 if (!_internal) { | 
|                     $(item).removeAttr("data-checked"); | 
|                 } | 
|             }); | 
|             this.checkboxRender(); | 
|         }, | 
|         unCheckArrNodes: function (arr) { | 
|             var options = this.config; | 
|             var dataChecked = []; | 
|             options.elem.find(".eleTree-hideen[eletree-status='1']").each(function (index, item) { | 
|                 var id = $(item).parent(".eleTree-node-content").parent(".eleTree-node").data(options.request.key); | 
|                 // 获取所有被选中项,并去除arr中包含的数据 | 
|                 if (arr.some(function (val) { | 
|                     return val == id; | 
|                 })) { | 
|                     // 如果id在arr数组中,则清除dom上面的checked数据 | 
|                     $(item).removeAttr("data-checked"); | 
|                     return; | 
|                 } | 
|                 dataChecked.push(id); | 
|             }) | 
|   | 
|             // 更新defaultCheckedKeys数据 | 
|             for (var j = 0; j < options.defaultCheckedKeys.length; j++) { | 
|                 if (!dataChecked.some(function (val) { | 
|                     return val == options.defaultCheckedKeys[j]; | 
|                 })) { | 
|                     options.defaultCheckedKeys.splice(j, 1); | 
|                     j--; | 
|                 } | 
|             } | 
|             this.unCheckNodes(true); | 
|             this.defaultChecked(dataChecked); | 
|         }, | 
|         unExpandAll: function () { | 
|             var options = this.config; | 
|             options.elem.find(".layui-icon.icon-rotate").removeClass("icon-rotate") | 
|                 .parent(".eleTree-node-content-icon").parent(".eleTree-node-content") | 
|                 .siblings(".eleTree-node-group").children(".eleTree-node").hide(); | 
|         }, | 
|         // 节点事件 | 
|         nodeEvent: function () { | 
|             var _self = this; | 
|             var options = this.config; | 
|             // 节点被点击的回调事件 | 
|             options.elem.on("click", ".eleTree-node-content", function (e) { | 
|                 var eleNode = $(this).parent(".eleTree-node"); | 
|                 $("#tree-menu").hide().remove(); | 
|                 layui.event.call(eleNode, MOD_NAME, 'nodeClick(' + _self.filter + ')', { | 
|                     node: eleNode, | 
|                     data: _self.reInitData(eleNode), | 
|                     event: e | 
|                 }); | 
|             }) | 
|             // 节点右键的回调事件 | 
|             options.elem.on("contextmenu", ".eleTree-node-content", function (e) { | 
|                 var eleNode = $(this).parent(".eleTree-node"); | 
|                 layui.event.call(eleNode, MOD_NAME, 'nodeContextmenu(' + _self.filter + ')', { | 
|                     node: eleNode, | 
|                     data: _self.reInitData(eleNode), | 
|                     event: e | 
|                 }); | 
|             }) | 
|             // 节点被拖拽的回调事件 | 
|             options.draggable && options.elem.on("mousedown", ".eleTree-node-content", function (e) { | 
|                 var time = 0; | 
|                 var eleNode = $(this).parent(".eleTree-node"); | 
|                 var eleFloor = Number(eleNode.attr("eletree-floor")); | 
|                 var groupNode = eleNode.parent(".eleTree-node-group"); | 
|   | 
|                 e.stopPropagation(); | 
|                 options.elem.css("user-select", "none"); | 
|                 var cloneNode = eleNode.clone(true); | 
|                 var temNode = eleNode.clone(true); | 
|   | 
|                 var x = e.clientX - options.elem.offset().left; | 
|                 var y = e.clientY - options.elem.offset().top; | 
|                 options.elem.append(cloneNode); | 
|                 cloneNode.css({ | 
|                     "display": "none", | 
|                     "opacity": 0.7, | 
|                     "position": "absolute", | 
|                     "background-color": "#f5f5f5", | 
|                     "width": "100%" | 
|                 }) | 
|   | 
|                 var currentData = _self.reInitData(eleNode); | 
|   | 
|                 var isStop = false; | 
|   | 
|                 $(document).on("mousemove", function (e) { | 
|                     // t为了区别click事件 | 
|                     time++; | 
|                     if (time > 2) { | 
|                         var xx = e.clientX - options.elem.offset().left + 10; | 
|                         var yy = e.clientY - options.elem.offset().top + $(document).scrollTop() - 5;   // 加上浏览器滚动高度 | 
|   | 
|                         cloneNode.css({ | 
|                             display: "block", | 
|                             left: xx + "px", | 
|                             top: yy + "px" | 
|                         }) | 
|                     } | 
|                 }).on("mouseup", function (e) { | 
|                     $(document).off("mousemove").off("mouseup"); | 
|                     var target = $(e.target).parents(".eleTree-node").eq(0); | 
|                     cloneNode.remove(); | 
|                     options.elem.css("user-select", "auto"); | 
|   | 
|   | 
|                     // 当前点击的是否时最外层 | 
|                     var isCurrentOuterMost = eleNode.parent().get(0).isEqualNode(options.elem.get(0)) | 
|                     // 目标是否时最外层 | 
|                     var isTargetOuterMost = $(e.target).get(0).isEqualNode(options.elem.get(0)) | 
|                     if (isTargetOuterMost) { | 
|                         target = options.elem; | 
|                     } | 
|                     // 判断是否超出边界 | 
|                     if (target.parents(options.elem).length === 0 && !isTargetOuterMost) { | 
|                         return; | 
|                     } | 
|                     // 判断初始与结束是否是同一个节点 | 
|                     if (target.get(0).isEqualNode(eleNode.get(0))) { | 
|                         return; | 
|                     } | 
|                     // 判断是否是父节点放到子节点 | 
|                     var tFloor = target.attr("eletree-floor"); | 
|                     var isInChild = false; | 
|                     eleNode.find("[eletree-floor='" + tFloor + "']").each(function () { | 
|                         if (this.isEqualNode(target.get(0))) { | 
|                             isInChild = true; | 
|                         } | 
|                     }) | 
|                     if (isInChild) { | 
|                         return; | 
|                     } | 
|   | 
|                     var targetData = _self.reInitData(target); | 
|                     layui.event.call(target, MOD_NAME, 'nodeDrag(' + _self.filter + ')', { | 
|                         current: { | 
|                             node: eleNode, | 
|                             data: currentData | 
|                         }, | 
|                         target: { | 
|                             node: target, | 
|                             data: targetData | 
|                         }, | 
|                         stop: function () { | 
|                             isStop = true; | 
|                         } | 
|                     }); | 
|                     // 拖拽是否取消 | 
|                     if (isStop) { | 
|                         return false; | 
|                     } | 
|   | 
|                     // 数据更改 | 
|                     var currList = currentData.parentData.data[options.request.children] | 
|                     var currIndex = currentData.parentData.childIndex | 
|                     var currData = currentData.currentData; | 
|                     var tarData = targetData.currentData; | 
|                     // 当前是否是最外层 | 
|                     isCurrentOuterMost ? options.data.splice(currIndex, 1) : currList.splice(currIndex, 1) | 
|                     // 目标是否是最外层 | 
|                     isTargetOuterMost ? options.data.push(currData) : (function () { | 
|                         !tarData[options.request.children] ? tarData[options.request.children] = [] : ""; | 
|                         tarData[options.request.children].push(currData); | 
|                     })() | 
|   | 
|                     // dom互换 | 
|                     eleNode.remove(); | 
|                     var floor = null; | 
|                     // 最外层判断 | 
|                     if (isTargetOuterMost) { | 
|                         target.append(temNode); | 
|                         floor = 0; | 
|                     } else { | 
|                         target.children(".eleTree-node-group").append(temNode); | 
|                         floor = Number(target.attr("eletree-floor")) + 1; | 
|                     } | 
|                     // 加floor和padding | 
|                     temNode.attr("eletree-floor", String(floor)); | 
|                     temNode.children(".eleTree-node-content").css("padding-left", floor * options.indent + "px"); | 
|                     // 通过floor差值计算子元素的floor | 
|                     var countFloor = eleFloor - floor; | 
|                     temNode.find(".eleTree-node").each(function (index, item) { | 
|                         var f = Number($(item).attr("eletree-floor")) - countFloor; | 
|                         $(item).attr("eletree-floor", String(f)); | 
|                         $(item).children(".eleTree-node-content").css("padding-left", f * options.indent + "px"); | 
|                     }) | 
|                     // 原dom去三角 | 
|                     var leaf = groupNode.children(".eleTree-node").length === 0; | 
|                     leaf && groupNode.siblings(".eleTree-node-content") | 
|                         .children(".eleTree-node-content-icon").children(".layui-icon") | 
|                         .removeClass("icon-rotate").css("color", "transparent"); | 
|                     // 当前的增加三角 | 
|                     var cLeaf = target.children(".eleTree-node-group").children(".eleTree-node").length === 0; | 
|                     !cLeaf && target.children(".eleTree-node-content") | 
|                         .children(".eleTree-node-content-icon").children(".layui-icon") | 
|                         .addClass("icon-rotate").removeAttr("style"); | 
|   | 
|                     _self.unCheckNodes(true); | 
|                     _self.defaultChecked(); | 
|                     _self.checkboxInit(); | 
|                 }) | 
|             }) | 
|         }, | 
|         rightClickMenu: function () { | 
|             var _self = this; | 
|             var options = this.config; | 
|             if (options.contextmenuList.length <= 0) { | 
|                 return; | 
|             } | 
|             $(document).on("click", function () { | 
|                 $("#tree-menu").hide().remove(); | 
|             }); | 
|   | 
|             var customizeMenu = [];   // 用户自定义的 | 
|             var internalMenu = ["copy", "add", "add.async", "insertBefore", "insertAfter", "append", "edit", "edit.async", "remove", "remove.async"];  // 系统自带的 | 
|             var customizeStr = ''; | 
|             options.contextmenuList.forEach(function (val) { | 
|                 if ($.inArray(val, internalMenu) === -1) { | 
|                     customizeMenu.push(val); | 
|                     customizeStr += '<li class="' + (val.eventName || val) + '"><a href="javascript:;">' + (val.text || val) + '</a></li>'; | 
|                 } | 
|             }) | 
|             var menuStr = ['<ul id="tree-menu">' | 
|                 , $.inArray("copy", options.contextmenuList) !== -1 ? '<li class="copy"><a href="javascript:;">复制</a></li>' : '' | 
|                 , ($.inArray("add", options.contextmenuList) !== -1 || $.inArray("add.async", options.contextmenuList) !== -1) ? '<li class="add"><a href="javascript:;">新增</a></li>' + | 
|                     '<li class="insertBefore"><a href="javascript:;">插入节点前</a></li>' + | 
|                     '<li class="insertAfter"><a href="javascript:;">插入节点后</a></li>' + | 
|                     '<li class="append"><a href="javascript:;">插入子节点</a></li>' : "" | 
|                 , ($.inArray("edit", options.contextmenuList) !== -1 || $.inArray("edit.async", options.contextmenuList) !== -1) ? '<li class="edit"><a href="javascript:;">修改</a></li>' : '' | 
|                 , ($.inArray("remove", options.contextmenuList) !== -1 || $.inArray("remove.async", options.contextmenuList) !== -1) ? '<li class="remove"><a href="javascript:;">删除</a></li>' : '' | 
|                 , customizeStr | 
|                 , '</ul>'].join(""); | 
|             this.treeMenu = $(menuStr); | 
|             options.elem.off("contextmenu").on("contextmenu", ".eleTree-node-content", function (e) { | 
|                 var that = this; | 
|                 e.stopPropagation(); | 
|                 e.preventDefault(); | 
|                 // 添加active背景 | 
|                 if (_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active"); | 
|                 $(this).addClass("eleTree-node-content-active"); | 
|                 var eleNode = $(this).parent(".eleTree-node"); | 
|                 var nodeData = _self.reInitData(eleNode); | 
|   | 
|                 // 菜单位置 | 
|                 $(document.body).after(_self.treeMenu); | 
|                 $("#tree-menu").find("li.append,li.insertAfter,li.insertBefore").hide(); | 
|                 $("#tree-menu").find(":not(li.append,li.insertAfter,li.insertBefore)").show(); | 
|                 $("#tree-menu").css({ | 
|                     left: e.clientX + $(document).scrollLeft(), | 
|                     top: e.clientY + $(document).scrollTop() | 
|                 }).show(); | 
|                 // 复制 | 
|                 $("#tree-menu li.copy").off().on("click", function () { | 
|                     var el = $(that).children(".eleTree-node-content-label").get(0); | 
|                     var selection = window.getSelection(); | 
|                     var range = document.createRange(); | 
|                     range.selectNodeContents(el); | 
|                     selection.removeAllRanges(); | 
|                     selection.addRange(range); | 
|                     document.execCommand('Copy', 'false', null); | 
|                     selection.removeAllRanges(); | 
|                 }); | 
|                 // 新增 | 
|                 $("#tree-menu li.add").off().on("click", function (e) { | 
|                     e.stopPropagation(); | 
|                     $(this).hide().siblings("li:not(.append,.insertAfter,.insertBefore)").hide(); | 
|                     $(this).siblings(".append,li.insertAfter,li.insertBefore").show(); | 
|                 }) | 
|                 // 添加的默认数据 | 
|                 var obj = {}; | 
|                 obj[options.request.key] = Date.now(); | 
|                 obj[options.request.name] = "未命名" + _self.nameIndex; | 
|                 if (options.lazy) { | 
|                     obj[options.request.isLeaf] = true; | 
|                 } | 
|   | 
|                 var arr = ["Append", "InsertBefore", "InsertAfter"]; | 
|                 arr.forEach(function (val) { | 
|                     var s = val[0].toLocaleLowerCase() + val.slice(1, val.length); | 
|                     $("#tree-menu li." + s).off().on("click", function (e) { | 
|                         var node = $(that).parent(".eleTree-node"); | 
|                         var key = node.data(options.request.key); | 
|                         var isStop = false; | 
|                         var s = val[0].toLocaleLowerCase() + val.slice(1, val.length); | 
|                         // 每次只能添加一条数据,不可以批量添加 | 
|                         _self[s](key, obj); | 
|                         var nodeArr = []; | 
|                         node.children(".eleTree-node-group").children(".eleTree-node").each(function (i, itemNode) { | 
|                             nodeArr.push(itemNode); | 
|                         }) | 
|                         node.siblings(".eleTree-node").each(function (i, itemNode) { | 
|                             nodeArr.push(itemNode); | 
|                         }) | 
|                         $.each(nodeArr, function (i, itemNode) { | 
|                             if (obj[options.request.key] === $(itemNode).data(options.request.key)) { | 
|                                 var label = $(itemNode).children(".eleTree-node-content").children(".eleTree-node-content-label").hide(); | 
|                                 var text = label.text(); | 
|                                 var inp = "<input type='text' value='" + obj[options.request.name] + "' class='eleTree-node-content-input' />"; | 
|                                 label.after(inp); | 
|   | 
|                                 label.siblings(".eleTree-node-content-input").focus().off().on("blur", function () { | 
|                                     var v = $(this).val(); | 
|                                     obj[options.request.name] = v; | 
|                                     var inpThis = this; | 
|   | 
|                                     layui.event.call(node, MOD_NAME, 'node' + val + '(' + _self.filter + ')', { | 
|                                         node: node, | 
|                                         data: nodeData.currentData, | 
|                                         newData: obj, | 
|                                         // 重新设置数据 | 
|                                         setData: function (o) { | 
|                                             // obj[options.request.key]=Date.now(); | 
|                                             obj[options.request.name] = v; | 
|                                             if (options.lazy) { | 
|                                                 obj[options.request.isLeaf] = true; | 
|                                             } | 
|                                             var newObj = $.extend({}, obj, o); | 
|                                             this.newData = newObj; | 
|                                             // 修改数据 | 
|                                             var d = _self.reInitData($(itemNode)).currentData; | 
|                                             d[options.request.name] = newObj[options.request.name]; | 
|                                             d[options.request.key] = newObj[options.request.key]; | 
|                                             // 修改dom | 
|                                             $(inpThis).siblings(".eleTree-node-content-label").text(newObj[options.request.name]).show(); | 
|                                             $(itemNode).attr("data-" + options.request.key, newObj[options.request.key]);  // 改变页面上面的显示的key,之后可以获取dom | 
|                                             $(itemNode).data(options.request.key, newObj[options.request.key]);          // 改变data数据,之后可以通过data获取key | 
|                                             $(inpThis).remove(); | 
|   | 
|                                             _self.nameIndex++; | 
|                                             isStop = true; | 
|                                         }, | 
|                                         // 停止添加 | 
|                                         stop: function () { | 
|                                             isStop = true; | 
|                                             this.newData = {}; | 
|                                             _self.remove(obj[options.request.key]); | 
|                                         } | 
|                                     }); | 
|   | 
|                                     // 不是异步添加 | 
|                                     if ($.inArray("add.async", options.contextmenuList) === -1) { | 
|                                         if (isStop) return; | 
|                                         // 修改数据 | 
|                                         _self.reInitData($(itemNode)).currentData[options.request.name] = v; | 
|                                         // 修改dom | 
|                                         $(this).siblings(".eleTree-node-content-label").text(v).show(); | 
|                                         $(this).remove(); | 
|   | 
|                                         _self.nameIndex++; | 
|                                     } | 
|                                 }).on("mousedown", function (e) { | 
|                                     // 防止input拖拽 | 
|                                     e.stopPropagation(); | 
|                                 }).on("click", function (e) { | 
|                                     e.stopPropagation(); | 
|                                 }) | 
|                             } | 
|                         }) | 
|                     }) | 
|                 }) | 
|   | 
|                 // 编辑 | 
|                 $("#tree-menu li.edit").off().on("click", function (e) { | 
|                     e.stopPropagation(); | 
|                     $("#tree-menu").hide().remove(); | 
|                     var node = $(that).parent(".eleTree-node"); | 
|                     var key = node.data(options.request.key); | 
|                     var label = $(that).children(".eleTree-node-content-label").hide(); | 
|                     var text = label.text(); | 
|                     var inp = "<input type='text' value='" + text + "' class='eleTree-node-content-input' />"; | 
|                     label.after(inp); | 
|                     label.siblings(".eleTree-node-content-input").focus().select().off().on("blur", function () { | 
|                         var val = $(this).val(); | 
|                         var isStop = false; | 
|                         var inpThis = this; | 
|                         layui.event.call(node, MOD_NAME, 'nodeEdit(' + _self.filter + ')', { | 
|                             node: node, | 
|                             value: val, | 
|                             data: nodeData.currentData, | 
|                             // 停止添加 | 
|                             stop: function () { | 
|                                 isStop = true; | 
|                                 $(inpThis).siblings(".eleTree-node-content-label").show(); | 
|                                 $(inpThis).remove(); | 
|                             }, | 
|                             async: function () { | 
|                                 if (isStop) return; | 
|                                 // 修改数据 | 
|                                 _self.reInitData(eleNode).currentData[options.request.name] = val; | 
|                                 // 修改dom | 
|                                 $(inpThis).siblings(".eleTree-node-content-label").text(val).show(); | 
|                                 $(inpThis).remove(); | 
|                             } | 
|                         }); | 
|                         // 不是异步 | 
|                         if ($.inArray("edit.async", options.contextmenuList) === -1) { | 
|                             if (isStop) return; | 
|                             // 修改数据 | 
|                             _self.reInitData(eleNode).currentData[options.request.name] = val; | 
|                             // 修改dom | 
|                             $(this).siblings(".eleTree-node-content-label").text(val).show(); | 
|                             $(this).remove(); | 
|                         } | 
|   | 
|                     }).on("mousedown", function (e) { | 
|                         // 防止input拖拽 | 
|                         e.stopPropagation(); | 
|                     }) | 
|                 }) | 
|                 // 删除 | 
|                 $("#tree-menu li.remove").off().on("click", function (e) { | 
|                     var node = $(that).parent(".eleTree-node"); | 
|                     var key = node.data(options.request.key); | 
|                     var isStop = false; | 
|                     layui.event.call(node, MOD_NAME, 'nodeRemove(' + _self.filter + ')', { | 
|                         node: node, | 
|                         data: nodeData.currentData, | 
|                         // 停止添加 | 
|                         stop: function () { | 
|                             isStop = true; | 
|                             return this; | 
|                         }, | 
|                         async: function () { | 
|                             if (isStop) return; | 
|                             _self.remove(key); | 
|                             return this; | 
|                         } | 
|                     }); | 
|                     // 不是异步 | 
|                     if ($.inArray("remove.async", options.contextmenuList) === -1) { | 
|                         if (isStop) return; | 
|                         _self.remove(key); | 
|                     } | 
|   | 
|                 }) | 
|   | 
|                 // 自定义菜单回调 | 
|                 customizeMenu.forEach(function (val) { | 
|                     var text = val.eventName || val; | 
|                     $("#tree-menu li." + text).off().on("click", function () { | 
|                         var node = $(that).parent(".eleTree-node"); | 
|                         var isStop = false; | 
|                         layui.event.call(node, MOD_NAME, 'node' + text.replace(text.charAt(0), text.charAt(0).toUpperCase()) + '(' + _self.filter + ')', { | 
|                             node: node, | 
|                             data: nodeData.currentData, | 
|                         }); | 
|                     }); | 
|                 }) | 
|   | 
|                 _self.prevClickEle = $(this); | 
|             }) | 
|         }, | 
|         search: function (value) { | 
|             var options = this.config; | 
|             if (!options.searchNodeMethod || typeof options.searchNodeMethod !== "function") { | 
|                 return; | 
|             } | 
|             var data = options.data; | 
|             // 数据递归 | 
|             var traverse = function (data) { | 
|                 data.forEach(function (val, index) { | 
|                     // 所有查找到的节点增加属性 | 
|                     val.visible = options.searchNodeMethod(value, val); | 
|                     if (val[options.request.children] && val[options.request.children].length > 0) { | 
|                         traverse(val[options.request.children]); | 
|                     } | 
|                     //如果当前节点属性为隐藏,判断其子节点是否有显示的,如果有,则当前节点改为显示 | 
|                     if (!val.visible) { | 
|                         var childSomeShow = false; | 
|                         if (val[options.request.children] && val[options.request.children].length > 0) { | 
|                             childSomeShow = val[options.request.children].some(function (v, i) { | 
|                                 return v.visible; | 
|                             }) | 
|                         } | 
|                         val.visible = childSomeShow; | 
|                     } | 
|                     // 通过节点的属性,显示隐藏各个节点,并添加删除搜索类 | 
|                     var el = options.elem.find("[data-" + options.request.key + "='" + val[options.request.key] + "']"); | 
|                     if (val.visible) { | 
|                         el.removeClass("eleTree-search-hide"); | 
|                         // 判断父节点是否展开,如果父节点没有展开,则子节点也不要显示 | 
|                         var parentEl = el.parent(".eleTree-node-group").parent(".eleTree-node"); | 
|                         var isParentOpen = parentEl.children(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon.layui-icon-triangle-r").hasClass("icon-rotate") | 
|                         if ((parentEl.length > 0 && isParentOpen) || parentEl.length === 0) { | 
|                             el.show(); | 
|                         } | 
|                     } else { | 
|                         el.hide().addClass("eleTree-search-hide"); | 
|                     } | 
|                     // 删除子层属性 | 
|                     // if(val[options.request.children] && val[options.request.children].length>0){ | 
|                     //     val[options.request.children].forEach(function(v,i) { | 
|                     //         delete v.visible; | 
|                     //     }) | 
|                     // } | 
|                 }) | 
|             } | 
|             traverse(data); | 
|             // 删除最外层属性 | 
|             var arr = []; | 
|             data.forEach(function (val) { | 
|                 arr.push(val.visible); | 
|                 // delete val.visible; | 
|             }) | 
|             var isNotext = options.elem.children(".eleTree-noText"); | 
|             // 如果第一层的所有的都隐藏,则显示文本 | 
|             if (arr.every(function (v) { | 
|                 return v === false; | 
|             })) { | 
|                 if (isNotext.length === 0) { | 
|                     laytpl(TPL_NoText()).render(options, function (string) { | 
|                         options.elem.append(string); | 
|                     }); | 
|                 } | 
|             } else { | 
|                 isNotext.remove(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     exports(MOD_NAME, eleTree); | 
| }) |