eleTree.js 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. /**
  2. * 基于layui的tree重写
  3. * author: hsianglee
  4. * 最近修改时间: 2019/01/07
  5. */
  6. layui.define(["jquery","laytpl"], function (exports) {
  7. var $ = layui.jquery;
  8. var laytpl = layui.laytpl;
  9. var hint = layui.hint();
  10. var MOD_NAME="eleTree";
  11. //外部接口
  12. var eleTree={
  13. //事件监听
  14. on: function(events, callback){
  15. return layui.onevent.call(this, MOD_NAME, events, callback);
  16. },
  17. render: function(options) {
  18. var inst = new Class(options);
  19. return thisTree.call(inst);
  20. }
  21. }
  22. var thisTree=function() {
  23. var _self=this;
  24. var options = _self.config;
  25. // 暴漏外面的方法
  26. return {
  27. // 接收两个参数,1. 节点 key 2. 节点数据的数组
  28. updateKeyChildren: function(key,data) {
  29. if(options.data.length===0) return;
  30. return _self.updateKeyChildren.call(_self,key,data);
  31. },
  32. updateKeySelf: function(key,data) {
  33. if(options.data.length===0) return;
  34. return _self.updateKeySelf.call(_self,key,data);
  35. },
  36. remove: function(key) {
  37. if(options.data.length===0) return;
  38. return _self.remove.call(_self,key);
  39. },
  40. append: function(key,data) {
  41. if(options.data.length===0) return;
  42. return _self.append.call(_self,key,data);
  43. },
  44. insertBefore: function(key,data) {
  45. if(options.data.length===0) return;
  46. return _self.insertBefore.call(_self,key,data);
  47. },
  48. insertAfter: function(key,data) {
  49. if(options.data.length===0) return;
  50. return _self.insertAfter.call(_self,key,data);
  51. },
  52. // 接收两个 boolean 类型的参数,1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false
  53. getChecked: function(leafOnly, includeHalfChecked) {
  54. if(options.data.length===0) return;
  55. return _self.getChecked.call(_self,leafOnly, includeHalfChecked);
  56. },
  57. // 接收勾选节点数据的数组
  58. setChecked: function(data) {
  59. if(options.data.length===0) return;
  60. return _self.setChecked.call(_self,data);
  61. },
  62. // 取消选中
  63. unCheckNodes: function() {
  64. if(options.data.length===0) return;
  65. return _self.unCheckNodes.call(_self);
  66. },
  67. expandAll: function() {
  68. options.elem.children(".eleTree-node").children(".eleTree-node-group").empty();
  69. _self.expandAll.call(_self,options.data,[],1,true);
  70. _self.unCheckNodes();
  71. _self.defaultChecked();
  72. },
  73. unExpandAll: function() {
  74. return _self.unExpandAll.call(_self);
  75. },
  76. reload: function(options) {
  77. return _self.reload.call(_self,options);
  78. },
  79. search: function(value) {
  80. return _self.search.call(_self,value);
  81. }
  82. }
  83. }
  84. // 模板渲染
  85. var TPL_ELEM=function(options,floor,parentStatus) {
  86. return [
  87. '{{# for(var i=0;i<d.length;i++){ }}',
  88. '<div class="eleTree-node" data-'+options.request.key+'="{{d[i]["'+options.request.key+'"]}}" eletree-floor="'+floor+'" style="display: none;">',
  89. '<div class="eleTree-node-content" style="padding-left: '+(options.indent*floor)+'px;">',
  90. '<span class="eleTree-node-content-icon">',
  91. '<i class="layui-icon layui-icon-triangle-r ',
  92. function() {
  93. if(options.lazy){
  94. var str=[
  95. '{{# if(!d[i]["'+options.request.isLeaf+'"]){ }}',
  96. 'lazy-icon" ></i>',
  97. '{{# }else{ }}',
  98. 'leaf-icon" style="color: transparent;" ></i>',
  99. '{{# } }}'
  100. ].join("");
  101. return str;
  102. }
  103. return ['{{# if(!d[i]["'+options.request.children+'"] || d[i]["'+options.request.children+'"].length===0){ }}',
  104. 'leaf-icon" style="color: transparent;"',
  105. '{{# } }}',
  106. '"></i>'
  107. ].join("");
  108. }(),
  109. '</span>',
  110. function() {
  111. if(options.showCheckbox){
  112. var status="";
  113. if(parentStatus==="1"){
  114. status='"1" checked';
  115. }else if(parentStatus==="2"){
  116. status='"2"';
  117. }else{
  118. status='"0"';
  119. }
  120. return [
  121. '{{# if(d[i]["'+options.request.checked+'"]) { }}',
  122. '<input type="checkbox" name="eleTree-node" eleTree-status="1" checked class="eleTree-hideen ',
  123. '{{# }else{ }}',
  124. '<input type="checkbox" name="eleTree-node" eleTree-status='+status+' class="eleTree-hideen ',
  125. '{{# } }}',
  126. '{{# if(d[i]["'+options.request.disabled+'"]) { }}',
  127. 'eleTree-disabled',
  128. '{{# } }}',
  129. '" />'
  130. ].join("");
  131. }
  132. return ''
  133. }(),
  134. '<span class="eleTree-node-content-label">{{d[i]["'+options.request.name+'"]}}</span>',
  135. '</div>',
  136. '<div class="eleTree-node-group">',
  137. '</div>',
  138. '</div>',
  139. '{{# } }}'
  140. ].join("");
  141. }
  142. var TPL_NoText=function() {
  143. return '<h3 class="eleTree-noText" style="text-align: center;height: 30px;line-height: 30px;color: #888;">{{d.emptText}}</h3>';
  144. }
  145. var Class=function(options) {
  146. options.response=$.extend({}, this.config.response, options.response);
  147. options.request=$.extend({}, this.config.request, options.request);
  148. this.config = $.extend({}, this.config, options);
  149. this.prevClickEle=null;
  150. this.addKeyIndex=20181201;
  151. this.nameIndex=1;
  152. this.render();
  153. };
  154. Class.prototype={
  155. constructor: Class,
  156. config: {
  157. elem: "",
  158. data: [],
  159. emptText: "暂无数据", // 内容为空的时候展示的文本
  160. renderAfterExpand: true, // 是否在第一次展开某个树节点后才渲染其子节点
  161. highlightCurrent: false, // 是否高亮当前选中节点,默认值是 false。
  162. defaultExpandAll: false, // 是否默认展开所有节点
  163. expandOnClickNode: true, // 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。
  164. checkOnClickNode: false, // 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。
  165. defaultExpandedKeys: [], // 默认展开的节点的 key 的数组
  166. autoExpandParent: true, // 展开子节点的时候是否自动展开父节点
  167. showCheckbox: false, // 节点是否可被选择
  168. checkStrictly: false, // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false
  169. defaultCheckedKeys: [], // 默认勾选的节点的 key 的数组
  170. accordion: false, // 是否每次只打开一个同级树节点展开(手风琴效果)
  171. indent: 16, // 相邻级节点间的水平缩进,单位为像素
  172. lazy: false, // 是否懒加载子节点,需与 load 方法结合使用
  173. load: function() {}, // 加载子树数据的方法,仅当 lazy 属性为true 时生效
  174. draggable: false, // 是否开启拖拽节点功能
  175. contextmenuList: [], // 启用右键菜单,支持的操作有:"copy","add","edit","remove"
  176. searchNodeMethod: null, // 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏
  177. method: "get",
  178. url: "",
  179. contentType: "",
  180. headers: {},
  181. done: null,
  182. response: {
  183. statusName: "code",
  184. statusCode: 0,
  185. dataName: "data"
  186. },
  187. request: {
  188. name: "label",
  189. key: "id",
  190. children: "children",
  191. disabled: "disabled",
  192. checked: "checked",
  193. isLeaf: "isLeaf"
  194. }
  195. },
  196. render: function() {
  197. if(this.config.indent>30){
  198. this.config.indent=30;
  199. }else if(this.config.indent<10){
  200. this.config.indent=10;
  201. }
  202. var options=this.config;
  203. options.where=options.where || {};
  204. if(!options.elem) return hint.error("缺少elem参数");
  205. options.elem=typeof options.elem === "string" ? $(options.elem) : options.elem;
  206. this.filter=options.elem.attr("lay-filter");
  207. // load加载框
  208. 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>')
  209. // 判断加载方式
  210. if(options.data.length===0){
  211. this.ajaxGetData();
  212. }else{
  213. this.renderData();
  214. }
  215. },
  216. renderData: function() {
  217. var options=this.config;
  218. // 渲染第一层
  219. laytpl(TPL_ELEM(options,0)).render(options.data, function(string){
  220. options.elem.html(string).children().show();
  221. });
  222. // 懒加载 > 展开所有 > 初始展开项 > 初始渲染所有子节点 > 初始选中项 > 每次点击只渲染当前层(默认)
  223. // 判断所有dom是否全部加载
  224. if(!options.lazy){
  225. if(!options.renderAfterExpand || options.defaultExpandAll || options.defaultExpandedKeys.length>0 || options.defaultCheckedKeys.length>0){
  226. this.expandAll(options.data,[],1);
  227. }
  228. }
  229. this.eleTreeEvent();
  230. this.checkboxRender();
  231. this.checkboxEvent();
  232. this.defaultChecked();
  233. this.nodeEvent();
  234. this.rightClickMenu();
  235. if(!options.checkStrictly){
  236. this.checkboxInit();
  237. }
  238. },
  239. ajaxGetData: function() {
  240. var options=this.config;
  241. var _self=this;
  242. if(!options.url) {
  243. laytpl(TPL_NoText()).render(options, function(string){
  244. options.elem.html(string);
  245. });
  246. return;
  247. }
  248. var data = $.extend({}, options.where);
  249. if(options.contentType && options.contentType.indexOf("application/json") == 0){ //提交 json 格式
  250. data = JSON.stringify(data);
  251. }
  252. $.ajax({
  253. type: options.method || 'get'
  254. ,url: options.url
  255. ,contentType: options.contentType
  256. ,data: data
  257. ,dataType: 'json'
  258. ,headers: options.headers || {}
  259. ,success: function(res){
  260. if(res[options.response.statusName] != options.response.statusCode || !res[options.response.dataName]){
  261. hint.error("请检查数据格式是否符合规范");
  262. typeof options.done === 'function' && options.done(res);
  263. return;
  264. }
  265. options.data=res[options.response.dataName];
  266. _self.renderData();
  267. typeof options.done === 'function' && options.done(res);
  268. }
  269. });
  270. },
  271. reload: function(options) {
  272. var _self=this;
  273. if(this.config.data && this.config.data.constructor === Array) this.config.data=[];
  274. this.config = $.extend({}, this.config, options);
  275. $(this.config.elem).off(); // 取消事件绑定,防止多次绑定事件
  276. // reload记录选中的数据
  277. // this.getChecked().forEach(function(val) {
  278. // if($.inArray(val.key,this.config.defaultCheckedKeys)===-1){
  279. // this.config.defaultCheckedKeys.push(val.key);
  280. // }
  281. // },this);
  282. return eleTree.render(this.config)
  283. },
  284. // 下拉
  285. eleTreeEvent: function() {
  286. var _self=this;
  287. var options=this.config;
  288. // 下拉
  289. var expandOnClickNode=options.expandOnClickNode?".eleTree-node-content":".eleTree-node-content>.eleTree-node-content-icon";
  290. options.elem.on("click",expandOnClickNode,function(e) {
  291. e.stopPropagation();
  292. var eleTreeNodeContent=$(this).parent(".eleTree-node").length===0?$(this).parent(".eleTree-node-content"):$(this);
  293. var eleNode=eleTreeNodeContent.parent(".eleTree-node");
  294. var sibNode=eleTreeNodeContent.siblings(".eleTree-node-group");
  295. var el=eleTreeNodeContent.children(".eleTree-node-content-icon").children(".layui-icon");
  296. // 添加active背景
  297. if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active");
  298. if(options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active");
  299. _self.prevClickEle=eleTreeNodeContent;
  300. if(el.hasClass("icon-rotate")){
  301. // 合并
  302. sibNode.children(".eleTree-node:not(.eleTree-search-hide)").hide("fast");
  303. el.removeClass("icon-rotate");
  304. return;
  305. }
  306. if(sibNode.children(".eleTree-node").length===0){
  307. var floor=Number(eleNode.attr("eletree-floor"))+1;
  308. var data=_self.reInitData(eleNode);
  309. var d=data.currentData;
  310. // 是否懒加载
  311. if(options.lazy && el.hasClass("lazy-icon")){
  312. el.removeClass("layui-icon-triangle-r").addClass("layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop");
  313. options.load(d,function(getData) {
  314. d[options.request.children]=getData;
  315. var eletreeStatus=eleTreeNodeContent.children("input.eleTree-hideen").attr("eletree-status");
  316. if(d[options.request.children] && d[options.request.children].length>0){
  317. laytpl(TPL_ELEM(options,floor,eletreeStatus)).render(d[options.request.children], function(string){
  318. sibNode.append(string).children().show("fast");
  319. });
  320. }else{
  321. el.css("color","transparent").addClass("leaf-icon");
  322. }
  323. el.removeClass("lazy-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop").addClass("layui-icon-triangle-r icon-rotate");
  324. _self.checkboxRender();
  325. // 懒加载子元素选择祖父(待写)
  326. })
  327. }else{
  328. var eletreeStatus=eleTreeNodeContent.children("input.eleTree-hideen").attr("eletree-status");
  329. d[options.request.children] && d[options.request.children].length>0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render(d[options.request.children], function(string){
  330. sibNode.append(string);
  331. });
  332. // 选择祖父
  333. var eleNode1=sibNode.children(".eleTree-node").eq(0);
  334. if(eleNode1.length===0){
  335. _self.checkboxRender();
  336. return;
  337. }
  338. var siblingNode1=eleNode1.siblings(".eleTree-node");
  339. var item1=eleNode1.children(".eleTree-node-content").children(".eleTree-hideen").get(0);
  340. _self.selectParents(item1,eleNode1,siblingNode1);
  341. _self.checkboxRender();
  342. }
  343. }
  344. // 显示隐藏没有搜索类的
  345. sibNode.children(".eleTree-node:not(.eleTree-search-hide)").show("fast");
  346. el.addClass("icon-rotate");
  347. // 手风琴效果
  348. if(options.accordion){
  349. var node=eleTreeNodeContent.parent(".eleTree-node").siblings(".eleTree-node");
  350. node.children(".eleTree-node-group").children(".eleTree-node:not(.eleTree-search-hide)").hide("fast");
  351. node.children(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").removeClass("icon-rotate");
  352. }
  353. })
  354. },
  355. // checkbox选中
  356. checkboxEvent: function() {
  357. var options=this.config;
  358. var _self=this;
  359. var checkOnClickNode=options.checkOnClickNode?".eleTree-node-content":".eleTree-checkbox";
  360. // input添加属性eleTree-status:即input的三种状态,"0":未选中,"1":选中,"2":子孙部分选中
  361. options.elem.on("click",checkOnClickNode,function(e,type) {
  362. e.stopPropagation();
  363. var eleTreeNodeContent=$(this).parent(".eleTree-node").length===0?$(this).parent(".eleTree-node-content"):$(this);
  364. var checkbox=eleTreeNodeContent.children(".eleTree-checkbox");
  365. if(checkbox.hasClass("eleTree-checkbox-disabled")) return;
  366. // 获取点击所在数据
  367. var node=eleTreeNodeContent.parent(".eleTree-node");
  368. // var d=_self.reInitData(node).currentData;
  369. // 实际的input
  370. var inp=checkbox.siblings(".eleTree-hideen").get(0);
  371. var childNode=eleTreeNodeContent.siblings(".eleTree-node-group").find("input[name='eleTree-node']");
  372. // 添加active背景
  373. if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active");
  374. if(options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active");
  375. _self.prevClickEle=eleTreeNodeContent;
  376. if(!inp){
  377. return;
  378. }
  379. if(inp.checked){
  380. // 反选自身
  381. $(inp).prop("checked",false).attr("eleTree-status","0");
  382. // 点击祖父层选中子孙层
  383. if(!options.checkStrictly){
  384. childNode.prop("checked",false);
  385. childNode.attr("eleTree-status","0");
  386. }
  387. }else{
  388. // 反选自身
  389. $(inp).prop("checked",true).attr("eleTree-status","1");
  390. // 点击祖父层选中子孙层
  391. if(!options.checkStrictly){
  392. childNode.prop("checked",true).attr("eleTree-status","1");
  393. }
  394. }
  395. var eleNode=eleTreeNodeContent.parent(".eleTree-node");
  396. // 点击子孙层选中祖父层(递归)
  397. if(!options.checkStrictly){
  398. var siblingNode=eleNode.siblings(".eleTree-node");
  399. // 点击子孙层选中祖父层(递归)
  400. _self.selectParents(inp,eleNode,siblingNode);
  401. }
  402. _self.checkboxRender();
  403. if(type==="default") return;
  404. layui.event.call(inp, MOD_NAME, 'nodeChecked('+ _self.filter +')', {
  405. node: eleNode,
  406. data: _self.reInitData(eleNode),
  407. isChecked: inp.checked
  408. });
  409. })
  410. },
  411. // 对后台数据有 checked:true 的默认选中项渲染父子层
  412. checkboxInit: function() {
  413. var options=this.config;
  414. var _self=this;
  415. options.elem.find("input[eleTree-status='1']").each(function(index,item) {
  416. var checkboxEl=$(item).siblings(".eleTree-checkbox");
  417. var childNode=checkboxEl.parent(".eleTree-node-content").siblings(".eleTree-node-group").find("input[name='eleTree-node']");
  418. // 选择当前
  419. checkboxEl.addClass("eleTree-checkbox-checked");
  420. checkboxEl.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  421. // 选择子孙
  422. childNode.prop("checked","checked").attr("eleTree-status","1");
  423. childNode.siblings(".eleTree-checkbox").addClass("eleTree-checkbox-checked");
  424. childNode.siblings(".eleTree-checkbox").children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  425. // 选择祖父
  426. var eleNode=checkboxEl.parent(".eleTree-node-content").parent(".eleTree-node");
  427. var siblingNode=eleNode.siblings(".eleTree-node");
  428. _self.selectParents(item,eleNode,siblingNode);
  429. })
  430. _self.checkboxRender();
  431. },
  432. // 通过子元素选中祖父元素
  433. selectParents: function(inp,eleNode,siblingNode) {
  434. // inp: 实际input(dom元素)
  435. // eleNode: input父层类(.eleTree-node)
  436. // siblingNode: 父层同级兄弟
  437. while (Number(eleNode.attr("eletree-floor"))!==0) {
  438. // 同级input状态存入数组
  439. var arr=[];
  440. arr.push($(inp).attr("eleTree-status"));
  441. siblingNode.each(function(index,item) {
  442. var siblingIsChecked=$(item).children(".eleTree-node-content").children("input[name='eleTree-node']").attr("eleTree-status");
  443. arr.push(siblingIsChecked);
  444. })
  445. // 父元素的实际input
  446. var parentInput=eleNode.parent(".eleTree-node-group").siblings(".eleTree-node-content").children("input[name='eleTree-node']");
  447. // 父元素的checkbox替代
  448. var parentCheckbox=parentInput.siblings(".eleTree-checkbox");
  449. // 子都选中则选中父
  450. if(arr.every(function(val) {
  451. return val==="1";
  452. })){
  453. parentInput.prop("checked",true).attr("eleTree-status","1");
  454. }
  455. // 子有一个未选中则checkbox第三种状态
  456. if(arr.some(function(val) {
  457. return val==="0" || val==="2";
  458. })){
  459. parentInput.attr("eleTree-status","2");
  460. }
  461. // 子全部未选中则取消父选中(并且取消第三种状态)
  462. if(arr.every(function(val) {
  463. return val==="0";
  464. })){
  465. parentInput.prop("checked",false);
  466. parentInput.attr("eleTree-status","0");
  467. }
  468. var parentNode=eleNode.parents("[eletree-floor='"+(Number(eleNode.attr("eletree-floor"))-1)+"']");
  469. var parentCheckbox=parentNode.children(".eleTree-node-content").children("input[name='eleTree-node']").get(0);
  470. var parentSiblingNode=parentNode.siblings(".eleTree-node");
  471. eleNode=parentNode;
  472. inp=parentCheckbox;
  473. siblingNode=parentSiblingNode;
  474. }
  475. },
  476. // 初始展开所有
  477. expandAll: function(data,arr,floor,isMethodsExpandAll) {
  478. var options=this.config;
  479. var _self=this;
  480. data.forEach(function(val,index) {
  481. arr.push(index);
  482. if(val[options.request.children] && val[options.request.children].length>0){
  483. var el=options.elem.children(".eleTree-node").eq(arr[0]).children(".eleTree-node-group");
  484. for(var i=1;i<arr.length;i++){
  485. el=el.children(".eleTree-node").eq(arr[i]).children(".eleTree-node-group");
  486. }
  487. laytpl(TPL_ELEM(options,floor)).render(val[options.request.children], function(string){
  488. el.append(string);
  489. // 判断是否展开所有
  490. if(options.defaultExpandAll || isMethodsExpandAll){
  491. el.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate");
  492. el.children().show();
  493. }else if(options.defaultExpandedKeys.length>0) {
  494. // 展开指定id项
  495. var id=el.parent(".eleTree-node").attr("data-"+options.request.key);
  496. id=isNaN(id) ? id : Number(id);
  497. if($.inArray(id,options.defaultExpandedKeys)!==-1){
  498. el.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate");
  499. el.children().show();
  500. // 展开子项是否继续展开祖父项
  501. if(options.autoExpandParent){
  502. var eleP=el.parent(".eleTree-node[data-"+options.request.key+"]").parents(".eleTree-node");
  503. eleP.each(function(i,item) {
  504. if($(item).attr("data-"+options.request.key)){
  505. $(item).children(".eleTree-node-group").siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate");
  506. $(item).children(".eleTree-node-group").children().show();
  507. }
  508. })
  509. }
  510. }
  511. }
  512. });
  513. floor++;
  514. _self.expandAll(val[options.request.children],arr,floor,isMethodsExpandAll);
  515. floor--;
  516. }
  517. // 重置数组索引
  518. arr.pop();
  519. })
  520. },
  521. // 初始默认选中
  522. defaultChecked: function() {
  523. var options=this.config;
  524. if(options.defaultCheckedKeys.length===0){
  525. return false;
  526. }
  527. // 判断是否父子无关
  528. if(options.checkStrictly){
  529. options.defaultCheckedKeys.forEach(function(val,index) {
  530. var nodeContent=options.elem.find("[data-"+options.request.key+"='"+val+"']").children(".eleTree-node-content");
  531. // 如果当前没选中则选中
  532. if(nodeContent.children(".eleTree-hideen").prop("checked")===false){
  533. nodeContent.children(".eleTree-checkbox").trigger("click",["default"]);
  534. }
  535. })
  536. return false;
  537. }
  538. // 父元素优先
  539. var arr=$.extend([],options.defaultCheckedKeys);
  540. options.defaultCheckedKeys.forEach(function(val,index) {
  541. options.elem.find("[data-"+options.request.key+"='"+val+"']").find("[data-"+options.request.key+"]").each(function(i,item) {
  542. var id=$(item).attr("data-"+options.request.key);
  543. id=isNaN(id) ? id : Number(id);
  544. var isInArrayIndex=$.inArray(id,arr);
  545. if(isInArrayIndex!==-1){
  546. arr.splice(isInArrayIndex,1);
  547. }
  548. })
  549. })
  550. arr.forEach(function(val,index) {
  551. var nodeContent=options.elem.find("[data-"+options.request.key+"='"+val+"']").children(".eleTree-node-content");
  552. // 如果当前没选中则选中
  553. if(nodeContent.children(".eleTree-hideen").prop("checked")===false){
  554. nodeContent.children(".eleTree-checkbox").trigger("click",["default"]);
  555. }
  556. })
  557. },
  558. // 自定义checkbox解析
  559. checkboxRender: function() {
  560. var options=this.config;
  561. options.elem.find(".eleTree-checkbox").remove();
  562. options.elem.find("input.eleTree-hideen[type=checkbox]").each(function(index,item){
  563. if($(item).hasClass("eleTree-disabled")){
  564. $(item).after('<div class="eleTree-checkbox eleTree-checkbox-disabled"><i class="layui-icon"></i></div>');
  565. }else{
  566. $(item).after('<div class="eleTree-checkbox"><i class="layui-icon"></i></div>');
  567. }
  568. var checkbox=$(item).siblings(".eleTree-checkbox");
  569. if($(item).attr("eletree-status")==="1"){
  570. checkbox.addClass("eleTree-checkbox-checked");
  571. checkbox.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  572. }else if($(item).attr("eletree-status")==="0"){
  573. checkbox.removeClass("eleTree-checkbox-checked");
  574. checkbox.children("i").removeClass("layui-icon-ok eleTree-checkbox-line");
  575. }else if($(item).attr("eletree-status")==="2"){
  576. checkbox.addClass("eleTree-checkbox-checked");
  577. checkbox.children("i").removeClass("layui-icon-ok").addClass("eleTree-checkbox-line");
  578. }
  579. })
  580. },
  581. // 通过dom节点找对应数据
  582. reInitData: function(node) {
  583. var options=this.config;
  584. var i=node.index();
  585. var floor=Number(node.attr("eletree-floor"));
  586. var arr=[]; // 节点对应的index
  587. while (floor>=0) {
  588. arr.push(i);
  589. floor=floor-1;
  590. node=node.parents("[eletree-floor='"+floor+"']");
  591. i=node.index();
  592. }
  593. arr=arr.reverse();
  594. var oData=this.config.data;
  595. // 当前节点的父节点数据
  596. var parentData=oData[arr[0]];
  597. // 当前节点的data数据
  598. var d = oData[arr[0]];
  599. for(var i = 1; i<arr.length; i++){
  600. d = d[options.request.children]?d[options.request.children][arr[i]]:d;
  601. }
  602. for(var i = 1; i<arr.length-1; i++){
  603. parentData = parentData[options.request.children]?parentData[options.request.children][arr[i]]:parentData;
  604. }
  605. return {
  606. currentData: d,
  607. parentData: {
  608. data: parentData,
  609. childIndex: arr[arr.length-1]
  610. },
  611. index: arr
  612. }
  613. },
  614. // 通过key查找数据
  615. keySearchToOpera: function(key,callback) {
  616. var options=this.config;
  617. var _self=this;
  618. // 查找数据
  619. var fn=function(data) {
  620. var obj={
  621. i: 0,
  622. len: data.length
  623. }
  624. for(;obj.i<obj.len;obj.i++){
  625. if(data[obj.i][options.request.key]!==key){
  626. if(data[obj.i][options.request.children] && data[obj.i][options.request.children].length>0){
  627. fn(data[obj.i][options.request.children]);
  628. }
  629. }else{
  630. callback(data,obj);
  631. }
  632. }
  633. }
  634. fn(options.data);
  635. },
  636. updateKeyChildren: function(key,data) {
  637. var options=this.config;
  638. var node=options.elem.find("[data-"+options.request.key+"='"+key+"']");
  639. var floor=Number(node.attr("eletree-floor"))+1;
  640. var _self=this;
  641. this.keySearchToOpera(key,function(d,obj) {
  642. // 数据更新
  643. d[obj.i][options.request.children]=data;
  644. // dom更新
  645. node.length!==0 && laytpl(TPL_ELEM(options,floor)).render(data, function(string){
  646. $(node).children(".eleTree-node-group").empty().append(string);
  647. options.defaultExpandAll && $(node).children(".eleTree-node-group").children().show();
  648. });
  649. _self.unCheckNodes();
  650. _self.defaultChecked();
  651. });
  652. },
  653. updateKeySelf: function(key,data) {
  654. var options=this.config;
  655. var node=options.elem.find("[data-"+options.request.key+"='"+key+"']").children(".eleTree-node-content");
  656. var floor=Number(node.attr("eletree-floor"))+1;
  657. data[options.request.name] && node.children(".eleTree-node-content-label").text(data[options.request.name]);
  658. data[options.request.disabled] && node.children(".eleTree-hideen").addClass("eleTree-disabled")
  659. .siblings(".eleTree-checkbox").addClass("eleTree-checkbox-disabled");
  660. // 数据更新
  661. var getData=this.keySearchToOpera(key,function(d,obj) {
  662. data[options.request.key]=d[obj.i][options.request.key];
  663. data[options.request.children]=d[obj.i][options.request.children];
  664. d[obj.i]=$.extend({},d[obj.i],data);
  665. console.log(options.data);
  666. });
  667. },
  668. remove: function(key) {
  669. var options=this.config;
  670. var node=options.elem.find("[data-"+options.request.key+"='"+key+"']");
  671. var pElem=node.parent(".eleTree-node-group");
  672. // 数据删除
  673. this.keySearchToOpera(key,function(data,obj) {
  674. data.splice(obj.i,1);
  675. obj.i--;
  676. obj.len--;
  677. node.length!==0 && options.elem.find("[data-"+options.request.key+"='"+key+"']").remove();
  678. if(pElem.children(".eleTree-node").length===0){
  679. pElem.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").css("color", "transparent");
  680. }
  681. });
  682. this.unCheckNodes();
  683. this.defaultChecked();
  684. },
  685. append: function(key,data) {
  686. var options=this.config;
  687. var node=options.elem.find("[data-"+options.request.key+"='"+key+"']");
  688. var floor=Number(node.attr("eletree-floor"))+1;
  689. // 数据更新
  690. this.keySearchToOpera(key,function(d,obj) {
  691. if(d[obj.i][options.request.children]){
  692. d[obj.i][options.request.children].push(data);
  693. }else{
  694. d[obj.i][options.request.children]=[data];
  695. }
  696. var arr=d[obj.i][options.request.children];
  697. // 添加之后长度为1,则原来没有三角,添加三角
  698. if(arr.length===1){
  699. node.children(".eleTree-node-content").find(".eleTree-node-content-icon .layui-icon").removeAttr("style").addClass("icon-rotate");
  700. }
  701. var len=arr.length;
  702. var eletreeStatus=node.children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status");
  703. eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus;
  704. node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([arr[len-1]], function(string){
  705. node.children(".eleTree-node-group").append(string).children().show();
  706. });
  707. });
  708. this.checkboxRender();
  709. },
  710. insertBefore: function(key,data) {
  711. var options=this.config;
  712. var node=options.elem.find("[data-"+options.request.key+"='"+key+"']");
  713. var floor=Number(node.attr("eletree-floor"));
  714. // 数据更新
  715. this.keySearchToOpera(key,function(d,obj) {
  716. d.splice(obj.i,0,data);
  717. obj.i++;
  718. obj.len++;
  719. var eletreeStatus=node.parent(".eleTree-node-group").length===0 ? "0" : node.parent(".eleTree-node-group").parent(".eleTree-node")
  720. .children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status");
  721. eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus;
  722. node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([data], function(string){
  723. node.before(string).prev(".eleTree-node").show();
  724. });
  725. });
  726. this.checkboxRender();
  727. },
  728. insertAfter: function(key,data) {
  729. var options=this.config;
  730. var node=options.elem.find("[data-"+options.request.key+"='"+key+"']");
  731. var floor=Number(node.attr("eletree-floor"));
  732. // 数据更新
  733. this.keySearchToOpera(key,function(d,obj) {
  734. d.splice(obj.i+1,0,data);
  735. obj.i++;
  736. obj.len++;
  737. var eletreeStatus=node.parent(".eleTree-node-group").length===0 ? "0" : node.parent(".eleTree-node-group").parent(".eleTree-node")
  738. .children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status");
  739. eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus;
  740. node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([data], function(string){
  741. $(node).after(string).next(".eleTree-node").show();
  742. });
  743. });
  744. this.checkboxRender();
  745. // if(!options.lazy){
  746. // if(!options.renderAfterExpand || options.defaultExpandAll || options.defaultExpandedKeys.length>0){
  747. // this.expandAll(options.data,[],1);
  748. // }
  749. // }
  750. },
  751. getChecked: function(leafOnly, includeHalfChecked) {
  752. var options=this.config
  753. ,el
  754. ,arr=[];
  755. leafOnly=leafOnly || false;
  756. includeHalfChecked=includeHalfChecked || false;
  757. if(leafOnly){
  758. el=options.elem.find(".layui-icon.leaf-icon").parent(".eleTree-node-content-icon")
  759. .siblings("input.eleTree-hideen[eletree-status='1']");
  760. }else if(includeHalfChecked){
  761. el=options.elem.find("input.eleTree-hideen[eletree-status='1'],input.eleTree-hideen[eletree-status='2']");
  762. }else{
  763. el=options.elem.find("input.eleTree-hideen[eletree-status='1']");
  764. }
  765. el.each(function(index,item) {
  766. var obj={};
  767. var id=$(item).parent(".eleTree-node-content").parent(".eleTree-node").attr("data-"+options.request.key);
  768. id=isNaN(id) ? id : Number(id);
  769. obj[options.request.key]=id;
  770. obj.elem=item;
  771. obj.othis=$(item).siblings(".eleTree-checkbox").get(0)
  772. arr.push(obj);
  773. })
  774. return arr;
  775. },
  776. setChecked: function(arr) {
  777. var options=this.config;
  778. this.unCheckNodes();
  779. arr.forEach(function(val) {
  780. if($.inArray(val,options.defaultCheckedKeys)===-1){
  781. options.defaultCheckedKeys.push(val);
  782. }
  783. })
  784. this.defaultChecked();
  785. },
  786. unCheckNodes: function() {
  787. var options=this.config;
  788. options.elem.find("input.eleTree-hideen[eletree-status='1'],input.eleTree-hideen[eletree-status='2']").each(function(index,item) {
  789. $(item).attr("eletree-status","0").prop("checked",false);
  790. });
  791. this.checkboxRender();
  792. },
  793. unExpandAll: function() {
  794. var options=this.config;
  795. options.elem.find(".layui-icon.icon-rotate").removeClass("icon-rotate")
  796. .parent(".eleTree-node-content-icon").parent(".eleTree-node-content")
  797. .siblings(".eleTree-node-group").children(".eleTree-node").hide();
  798. },
  799. // 节点事件
  800. nodeEvent: function() {
  801. var _self=this;
  802. var options=this.config;
  803. // 节点被点击的回调事件
  804. options.elem.on("click",".eleTree-node-content",function(e) {
  805. var eleNode=$(this).parent(".eleTree-node");
  806. $("#tree-menu").hide().remove();
  807. layui.event.call(eleNode, MOD_NAME, 'nodeClick('+ _self.filter +')', {
  808. node: eleNode,
  809. data: _self.reInitData(eleNode),
  810. event: e
  811. });
  812. })
  813. // 节点右键的回调事件
  814. options.elem.on("contextmenu",".eleTree-node-content",function(e) {
  815. var eleNode=$(this).parent(".eleTree-node");
  816. layui.event.call(eleNode, MOD_NAME, 'nodeContextmenu('+ _self.filter +')', {
  817. node: eleNode,
  818. data: _self.reInitData(eleNode),
  819. event: e
  820. });
  821. })
  822. // 节点被拖拽的回调事件
  823. options.draggable && options.elem.on("mousedown",".eleTree-node-content",function(e) {
  824. var time=0;
  825. var eleNode=$(this).parent(".eleTree-node");
  826. var eleFloor=Number(eleNode.attr("eletree-floor"));
  827. var groupNode=eleNode.parent(".eleTree-node-group");
  828. e.stopPropagation();
  829. options.elem.css("user-select","none");
  830. var cloneNode=eleNode.clone(true);
  831. var temNode=eleNode.clone(true);
  832. var x=e.clientX-options.elem.offset().left;
  833. var y=e.clientY-options.elem.offset().top;
  834. options.elem.append(cloneNode);
  835. cloneNode.css({
  836. "display": "none",
  837. "opacity": 0.7,
  838. "position": "absolute",
  839. "background-color": "#f5f5f5",
  840. "width": "100%"
  841. })
  842. var currentData=_self.reInitData(eleNode);
  843. var isStop=false;
  844. $(document).on("mousemove",function(e) {
  845. // t为了区别click事件
  846. time++;
  847. if(time>2){
  848. var xx=e.clientX-options.elem.offset().left+10;
  849. var yy=e.clientY-options.elem.offset().top+$(document).scrollTop()-5; // 加上浏览器滚动高度
  850. cloneNode.css({
  851. display: "block",
  852. left: xx+"px",
  853. top: yy+"px"
  854. })
  855. }
  856. }).on("mouseup",function(e) {
  857. $(document).off("mousemove").off("mouseup");
  858. var target=$(e.target).parents(".eleTree-node").eq(0);
  859. cloneNode.remove();
  860. options.elem.css("user-select","auto");
  861. // 当前点击的是否时最外层
  862. var isCurrentOuterMost=eleNode.parent().get(0).isEqualNode(options.elem.get(0))
  863. // 目标是否时最外层
  864. var isTargetOuterMost=$(e.target).get(0).isEqualNode(options.elem.get(0))
  865. if(isTargetOuterMost){
  866. target=options.elem;
  867. }
  868. // 判断是否超出边界
  869. if(target.parents(options.elem).length===0 && !isTargetOuterMost){
  870. return;
  871. }
  872. // 判断初始与结束是否是同一个节点
  873. if(target.get(0).isEqualNode(eleNode.get(0))){
  874. return;
  875. }
  876. // 判断是否是父节点放到子节点
  877. var tFloor=target.attr("eletree-floor");
  878. var isInChild=false;
  879. eleNode.find("[eletree-floor='"+tFloor+"']").each(function() {
  880. if(this.isEqualNode(target.get(0))){
  881. isInChild=true;
  882. }
  883. })
  884. if(isInChild){
  885. return;
  886. }
  887. var targetData=_self.reInitData(target);
  888. layui.event.call(target, MOD_NAME, 'nodeDrag('+ _self.filter +')', {
  889. current: {
  890. node: eleNode,
  891. data: currentData
  892. },
  893. target: {
  894. node: target,
  895. data: targetData
  896. },
  897. stop: function() {
  898. isStop=true;
  899. }
  900. });
  901. // 拖拽是否取消
  902. if(isStop){
  903. return false;
  904. }
  905. // 数据更改
  906. var currList=currentData.parentData.data[options.request.children]
  907. var currIndex=currentData.parentData.childIndex
  908. var currData=currentData.currentData;
  909. var tarData=targetData.currentData;
  910. // 当前是否是最外层
  911. isCurrentOuterMost ? options.data.splice(currIndex,1) : currList.splice(currIndex,1)
  912. // 目标是否是最外层
  913. isTargetOuterMost ? options.data.push(currData) : (function() {
  914. !tarData[options.request.children] ? tarData[options.request.children]=[] : "";
  915. tarData[options.request.children].push(currData);
  916. })()
  917. // dom互换
  918. eleNode.remove();
  919. // 最外层判断
  920. if(isTargetOuterMost){
  921. target.append(temNode);
  922. var floor=0;
  923. }else{
  924. target.children(".eleTree-node-group").append(temNode);
  925. var floor=Number(target.attr("eletree-floor"))+1;
  926. }
  927. // 加floor和padding
  928. temNode.attr("eletree-floor",String(floor));
  929. temNode.children(".eleTree-node-content").css("padding-left",floor*options.indent+"px");
  930. // 通过floor差值计算子元素的floor
  931. var countFloor=eleFloor-floor;
  932. temNode.find(".eleTree-node").each(function(index,item) {
  933. var f=Number($(item).attr("eletree-floor"))-countFloor;
  934. $(item).attr("eletree-floor",String(f));
  935. $(item).children(".eleTree-node-content").css("padding-left",f*options.indent+"px");
  936. })
  937. // 原dom去三角
  938. var leaf=groupNode.children(".eleTree-node").length===0;
  939. leaf && groupNode.siblings(".eleTree-node-content")
  940. .children(".eleTree-node-content-icon").children(".layui-icon")
  941. .removeClass("icon-rotate").css("color","transparent");
  942. // 当前的增加三角
  943. var cLeaf=target.children(".eleTree-node-group").children(".eleTree-node").length===0;
  944. !cLeaf && target.children(".eleTree-node-content")
  945. .children(".eleTree-node-content-icon").children(".layui-icon")
  946. .addClass("icon-rotate").removeAttr("style");
  947. _self.unCheckNodes();
  948. _self.defaultChecked();
  949. })
  950. })
  951. },
  952. rightClickMenu: function() {
  953. var _self=this;
  954. var options=this.config;
  955. if(options.contextmenuList.length<=0){
  956. return;
  957. }
  958. $(document).on("click",function() {
  959. $("#tree-menu").hide().remove();
  960. });
  961. var menuStr=['<ul id="tree-menu">'
  962. ,$.inArray("copy",options.contextmenuList)!==-1?'<li class="copy"><a href="javascript:;">复制</a></li>':''
  963. ,$.inArray("add",options.contextmenuList)!==-1?'<li class="add"><a href="javascript:;">新增</a></li>'+
  964. '<li class="insertBefore"><a href="javascript:;">插入节点前</a></li>'+
  965. '<li class="insertAfter"><a href="javascript:;">插入节点后</a></li>'+
  966. '<li class="append"><a href="javascript:;">插入子节点</a></li>' : ""
  967. ,$.inArray("edit",options.contextmenuList)!==-1?'<li class="edit"><a href="javascript:;">修改</a></li>':''
  968. ,$.inArray("remove",options.contextmenuList)!==-1?'<li class="remove"><a href="javascript:;">删除</a></li>':''
  969. ,'</ul>'].join("");
  970. this.treeMenu=$(menuStr);
  971. options.elem.off("contextmenu").on("contextmenu",".eleTree-node-content",function(e) {
  972. var that=this;
  973. e.stopPropagation();
  974. e.preventDefault();
  975. // 添加active背景
  976. if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active");
  977. $(this).addClass("eleTree-node-content-active");
  978. var eleNode=$(this).parent(".eleTree-node");
  979. var nodeData=_self.reInitData(eleNode);
  980. // 菜单位置
  981. $(document.body).after(_self.treeMenu);
  982. $("#tree-menu li.insertBefore,#tree-menu li.insertAfter,#tree-menu li.append").hide();
  983. $("#tree-menu li.copy,#tree-menu li.add,#tree-menu li.edit,#tree-menu li.remove").show();
  984. $("#tree-menu").css({
  985. left: e.pageX,
  986. top: e.pageY
  987. }).show();
  988. // 复制
  989. $("#tree-menu li.copy").off().on("click",function() {
  990. var el = $(that).children(".eleTree-node-content-label").get(0);
  991. var selection = window.getSelection();
  992. var range = document.createRange();
  993. range.selectNodeContents(el);
  994. selection.removeAllRanges();
  995. selection.addRange(range);
  996. document.execCommand('Copy', 'false', null);
  997. selection.removeAllRanges();
  998. });
  999. // 新增
  1000. $("#tree-menu li.add").off().on("click",function(e) {
  1001. e.stopPropagation();
  1002. $(this).hide().siblings("li.copy,li.edit,li.remove").hide();
  1003. $(this).siblings(".append,li.insertAfter,li.insertBefore").show();
  1004. })
  1005. // 添加的默认数据
  1006. var obj={};
  1007. obj[options.request.key]=_self.addKeyIndex;
  1008. obj[options.request.name]="未命名"+_self.nameIndex;
  1009. var arr=["Append","InsertBefore","InsertAfter"];
  1010. arr.forEach(function(val) {
  1011. var s=val[0].toLocaleLowerCase()+val.slice(1,val.length);
  1012. $("#tree-menu li."+s).off().on("click",function(e) {
  1013. var node=$(that).parent(".eleTree-node");
  1014. var key=node.attr("data-"+options.request.key);
  1015. key=isNaN(key) ? key : Number(key);
  1016. var isStop=false;
  1017. var s=val[0].toLocaleLowerCase()+val.slice(1,val.length);
  1018. layui.event.call(node, MOD_NAME, 'node'+val+'('+ _self.filter +')', {
  1019. node: node,
  1020. data: nodeData.currentData,
  1021. // 重新设置数据
  1022. setData: function(o) {
  1023. _self[s](key,$.extend({},obj,o));
  1024. isStop=true;
  1025. },
  1026. // 停止添加
  1027. stop: function() {
  1028. isStop=true;
  1029. }
  1030. });
  1031. if(isStop) return;
  1032. _self[s](key,obj)
  1033. _self.nameIndex++;
  1034. _self.addKeyIndex++;
  1035. })
  1036. })
  1037. // 编辑
  1038. $("#tree-menu li.edit").off().on("click",function(e) {
  1039. e.stopPropagation();
  1040. $("#tree-menu").hide().remove();
  1041. var node=$(that).parent(".eleTree-node");
  1042. var key=node.attr("data-"+options.request.key);
  1043. key=isNaN(key) ? key : Number(key);
  1044. var label=$(that).children(".eleTree-node-content-label").hide();
  1045. var text=label.text();
  1046. var inp="<input type='text' value='"+text+"' class='eleTree-node-content-input' />";
  1047. label.after(inp);
  1048. label.siblings(".eleTree-node-content-input").focus().select().off().on("blur",function() {
  1049. var val=$(this).val();
  1050. var isStop=false;
  1051. var inpThis=this;
  1052. layui.event.call(node, MOD_NAME, 'nodeEdit('+ _self.filter +')', {
  1053. node: node,
  1054. value: val,
  1055. data: nodeData.currentData,
  1056. // 停止添加
  1057. stop: function() {
  1058. isStop=true;
  1059. $(inpThis).siblings(".eleTree-node-content-label").show();
  1060. $(inpThis).remove();
  1061. }
  1062. });
  1063. if(isStop) return;
  1064. // 修改数据
  1065. _self.reInitData(eleNode).currentData[options.request.name]=val;
  1066. // 修改dom
  1067. $(this).siblings(".eleTree-node-content-label").text(val).show();
  1068. $(this).remove();
  1069. }).on("mousedown",function(e) {
  1070. // 防止input拖拽
  1071. e.stopPropagation();
  1072. })
  1073. })
  1074. // 删除
  1075. $("#tree-menu li.remove").off().on("click",function(e) {
  1076. var node=$(that).parent(".eleTree-node");
  1077. var key=node.attr("data-"+options.request.key);
  1078. key=isNaN(key) ? key : Number(key);
  1079. var isStop=false;
  1080. layui.event.call(node, MOD_NAME, 'nodeRemove('+ _self.filter +')', {
  1081. node: node,
  1082. data: nodeData.currentData,
  1083. // 停止添加
  1084. stop: function() {
  1085. isStop=true;
  1086. }
  1087. });
  1088. if(isStop) return;
  1089. _self.remove(key);
  1090. })
  1091. _self.prevClickEle=$(this);
  1092. })
  1093. },
  1094. search: function(value) {
  1095. var options=this.config;
  1096. if(!options.searchNodeMethod || typeof options.searchNodeMethod !== "function"){
  1097. return;
  1098. }
  1099. var data=options.data;
  1100. // 数据递归
  1101. var traverse=function(data) {
  1102. data.forEach(function(val,index) {
  1103. // 所有查找到的节点增加属性
  1104. val.visible=options.searchNodeMethod(value,val);
  1105. if(val[options.request.children] && val[options.request.children].length>0){
  1106. traverse(val[options.request.children]);
  1107. }
  1108. //如果当前节点属性为隐藏,判断其子节点是否有显示的,如果有,则当前节点改为显示
  1109. if(!val.visible){
  1110. let childSomeShow = false;
  1111. if(val[options.request.children] && val[options.request.children].length>0){
  1112. childSomeShow=val[options.request.children].some(function(v,i) {
  1113. return v.visible;
  1114. })
  1115. }
  1116. val.visible = childSomeShow;
  1117. }
  1118. // 通过节点的属性,显示隐藏各个节点,并添加删除搜索类
  1119. var el=options.elem.find("[data-"+options.request.key+"='"+val[options.request.key]+"']");
  1120. if(val.visible){
  1121. el.removeClass("eleTree-search-hide");
  1122. // 判断父节点是否展开,如果父节点没有展开,则子节点也不要显示
  1123. var parentEl=el.parent(".eleTree-node-group").parent(".eleTree-node");
  1124. var isParentOpen=parentEl.children(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon.layui-icon-triangle-r").hasClass("icon-rotate")
  1125. if((parentEl.length>0 && isParentOpen) || parentEl.length===0){
  1126. el.show();
  1127. }
  1128. }else{
  1129. el.hide().addClass("eleTree-search-hide");
  1130. }
  1131. // 删除子层属性
  1132. if(val[options.request.children] && val[options.request.children].length>0){
  1133. val[options.request.children].forEach(function(v,i) {
  1134. delete v.visible;
  1135. })
  1136. }
  1137. })
  1138. }
  1139. traverse(data);
  1140. // 删除最外层属性
  1141. var arr=[];
  1142. data.forEach(function(val) {
  1143. arr.push(val.visible);
  1144. delete val.visible;
  1145. })
  1146. // 如果第一层的所有的都隐藏,则显示文本
  1147. if(arr.every(function(v) {
  1148. return v===false;
  1149. })){
  1150. laytpl(TPL_NoText()).render(options, function(string){
  1151. options.elem.append(string);
  1152. });
  1153. }else{
  1154. options.elem.children(".eleTree-noText").remove();
  1155. }
  1156. }
  1157. }
  1158. exports(MOD_NAME,eleTree);
  1159. })