eleTree.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. /**
  2. * 基于layui的tree重写
  3. * author: hsianglee
  4. * 最近修改时间: 2018/09/26
  5. */
  6. layui.define(["jquery", "laytpl", "layer", "form"], function (exports) {
  7. var $ = layui.jquery;
  8. var laytpl = layui.laytpl;
  9. var layer = layui.layer;
  10. var form = layui.form;
  11. function Class(option) {
  12. this.option = option; // 获取传入的数据
  13. this.elem = "";
  14. this.data = [];
  15. this.showCheckbox = this.option.showCheckbox;
  16. this.showIcon = this.option.showIcon;
  17. this.drag = this.option.drag;
  18. this.accordion = this.option.accordion;
  19. this.contextmenuList = [];
  20. this.node = ""; // 生成树的dom字符串
  21. this.checkedData = []; // 被选中的数据
  22. this.prevClickEle; // 记录上次点击的dom
  23. this.treeMenu = ""; // 右键菜单字符串
  24. this.filter = "";
  25. this.menuShow = this.option.menuShow;
  26. this.open = this.option.open;
  27. this.render();
  28. }
  29. Class.prototype = {
  30. constructor: Class,
  31. // 初始化参数数据
  32. render: function () {
  33. var self = this;
  34. self.option.elem ? (function () {
  35. self.elem = self.option.elem;
  36. })() : (function () {
  37. throw "缺少elem节点选择器";
  38. })();
  39. self.contextmenuList = self.option.contextmenuList ? self.option.contextmenuList : [];
  40. self.filter = $(self.elem).attr("lay-filter");
  41. // 判断data参数
  42. if (self.option.data) {
  43. self.data = self.option.data;
  44. self.init();
  45. return;
  46. }
  47. // 判断url参数
  48. if (self.option.url) {
  49. $.ajax({
  50. url: self.option.url,
  51. type: self.option.type ? self.option.type : "get",
  52. data: self.option.where ? self.option.where : {},
  53. success: function (data) {
  54. if (data.code === 0) {
  55. self.data = data.data;
  56. self.init();
  57. return;
  58. }
  59. layer.alert(data.Msg, { title: "选择器" + self.elem + "获取数据失败", icon: 2 });
  60. }
  61. });
  62. return;
  63. }
  64. throw "选择器" + self.elem + "缺少data或url参数";
  65. },
  66. // 初始化容器和标签
  67. init: function () {
  68. var self = this;
  69. this.node = "";
  70. $(this.elem).empty();
  71. $(this.elem).off();
  72. this.nodeInit(this.data, 0, false);
  73. $(this.elem).html(this.node);
  74. this.checkboxEvent();
  75. // 更新选中的数据
  76. this.getCheckedData();
  77. this.drag && this.nodeDrag();
  78. this.eleTreeEvent();
  79. this.eleTreeClick();
  80. this.contextmenuList.length && this.contextmenuList.length > 0 && this.rightClickMenu();
  81. this.checkInit();
  82. },
  83. // dom生成
  84. nodeInit: function (arr, count, spread) {
  85. // count: 第几层
  86. // spread: 是否不展开
  87. var self = this;
  88. var a = [];
  89. arr.forEach(function (val, index) {
  90. var b = ['<div class="eleTree-node ', spread ? 'eleTree-hide' : "", '" eleTree-floor="' + count + '">'
  91. , '<div class="eleTree-node-content" style="padding-left: ' + 18 * count + 'px;">'
  92. , '<span class="eleTree-node-content-icon">'
  93. // 判断叶子节点
  94. , (function () {
  95. if (val.children && val.children.length > 0) {
  96. var s = '<i class="layui-icon layui-icon-triangle-r ';
  97. if (val.spread) {
  98. s += 'icon-rotate';
  99. }
  100. s += ' "></i>'
  101. return s;
  102. } else {
  103. return '<i class="layui-icon layui-icon-triangle-r" style="color: transparent;"></i>'
  104. }
  105. })()
  106. , '</span>'
  107. // 判断是否启用checkbox
  108. , (function () {
  109. var s = '';
  110. if (self.showCheckbox) {
  111. s += '<input type="checkbox" value="' + val.id + '" name="eleTree-node"';
  112. if (val.checked == 1) {
  113. s += ' eleTree-status="1" checked '
  114. } else {
  115. s += ' eleTree-status="0"'
  116. }
  117. s += 'class="eleTree-hideen '
  118. if (self.open == 0) {
  119. val.disabled = true;
  120. if (val.disabled) {
  121. s += 'eleTree-disabled'
  122. }
  123. }
  124. s += '" >';
  125. }
  126. return s;
  127. })()
  128. , (function () {
  129. if (self.showIcon) {
  130. return '<span class="eleTree-node-content-iconfont"><i class="layui-icon iconfont">' + val.icon + '</i></span>'
  131. }
  132. })()
  133. , (function () {
  134. if (self.menuShow) {
  135. return '<span class="eleTree-node-content-label">' + val.name + '</span>'
  136. } else {
  137. return '<span class="eleTree-node-content-label">' + val.areaName + '</span>'
  138. }
  139. })()
  140. , (function () {
  141. if (val.status == 2) {
  142. return '<span class="eleTree-node-content-btn"><i class="layui-icon layui-forbid iconfont icon-forbid"></i></span>'
  143. }
  144. })()
  145. , (function () {
  146. if (val.status == 1) {
  147. return '<span class="eleTree-node-content-btn"><i class="layui-icon layui-lock iconfont icon-lock"></i></span>'
  148. }
  149. })()
  150. , '</div>'
  151. , '<div class="eleTree-node-group">'
  152. , (function () {
  153. if (val.children && val.children.length > 0) {
  154. return self.nodeInit(val.children, count + 1, !val.spread); // 获取已经遍历完的子节点
  155. }
  156. })()
  157. , '</div>'
  158. , '</div>'];
  159. a = a.concat(b);
  160. }, this);
  161. this.node = a.join("");
  162. return this.node; // 返回已经遍历完的子节点
  163. },
  164. // 手风琴效果
  165. accordionFn: function (ele, d) {
  166. if (!this.accordion) return;
  167. // 手风琴
  168. var parentSibling = ele.parent(".eleTree-node").siblings(".eleTree-node");
  169. parentSibling.children(".eleTree-node-group").children().slideUp("fast");
  170. parentSibling.children(".eleTree-node-content").find(".layui-icon-triangle-r").removeClass("icon-rotate");
  171. var parentData = d.parentData;
  172. // 最外层判断
  173. if (d.index.length === 1) {
  174. this.data.forEach(function (val, index) {
  175. if (index !== parentData.childIndex) {
  176. delete val.spread;
  177. }
  178. })
  179. } else {
  180. parentData.data.children.forEach(function (val, index) {
  181. if (index !== parentData.childIndex) {
  182. delete val.spread;
  183. }
  184. })
  185. }
  186. },
  187. // 展开合并动画
  188. eleTreeEvent: function () {
  189. var self = this;
  190. $(this.elem).on("click", ".eleTree-node-content-icon", function (e) {
  191. e.stopPropagation();
  192. // 获取点击所在数据
  193. var node = $(this).parents(".eleTree-node ");
  194. var data = self.reInitData(node);
  195. var d = data.currentData;
  196. // 切换下拉
  197. var el = $(this).find(".layui-icon-triangle-r");
  198. if (el.hasClass("icon-rotate")) {
  199. $(this).parent(".eleTree-node-content").siblings(".eleTree-node-group").children().slideUp("fast");
  200. el.removeClass("icon-rotate");
  201. // 数据修改
  202. delete d.spread;
  203. } else {
  204. $(this).parent(".eleTree-node-content").siblings(".eleTree-node-group").children().slideDown("fast");
  205. el.addClass("icon-rotate");
  206. // 数据修改
  207. d.spread = true;
  208. self.accordionFn($(this), data);
  209. }
  210. self.prevClickEle = $(this);
  211. // 数据返回
  212. layui.event.call(this, "eleTree", 'toggleSlide(' + self.filter + ')', {
  213. data: self.data
  214. , currentData: d
  215. });
  216. $("#tree-menu").hide().remove();
  217. });
  218. $(document).on("click", function () {
  219. $("#tree-menu").hide().remove();
  220. });
  221. },
  222. // 单击动画
  223. eleTreeClick: function () {
  224. var self = this;
  225. $(this.elem).on("click", ".eleTree-node-content", function (e) {
  226. if ($(this).find(".layui-lock").length > 0) {
  227. ;
  228. return true
  229. }
  230. e.stopPropagation();
  231. // 添加active背景
  232. $(".eleTree-node-content").removeClass("eleTree-node-content-active");
  233. $(this).addClass("eleTree-node-content-active");
  234. // 获取点击所在数据
  235. var node = $(this).parent(".eleTree-node ");
  236. var data = self.reInitData(node);
  237. var d = data.currentData;
  238. // 数据返回
  239. layui.event.call(this, "eleTree", 'click(' + self.filter + ')', {
  240. currentData: d
  241. });
  242. $("#tree-menu").hide().remove();
  243. });
  244. $(document).on("click", function () {
  245. $("#tree-menu").hide().remove();
  246. });
  247. },
  248. // 右键菜单
  249. rightClickMenu: function () {
  250. var self = this;
  251. var menuStr = ['<ul id="tree-menu" lay-filter="treeMenu">'
  252. , $.inArray("copy", this.contextmenuList) !== -1 ? '<li class="copy"><a href="javascript:;">复制</a></li>' : ''
  253. , $.inArray("add", this.contextmenuList) !== -1 ? '<li class="add"><a href="javascript:;">新增子区域</a></li>' : ''
  254. , $.inArray("edit", this.contextmenuList) !== -1 ? '<li class="edit"><a href="javascript:;">修改</a></li>' : ''
  255. , $.inArray("forbid", this.contextmenuList) !== -1 ? '<li class="forbid"><a href="javascript:;">禁用</a></li>' : ''
  256. , $.inArray("remove", this.contextmenuList) !== -1 ? '<li class="remove"><a href="javascript:;">删除</a></li>' : ''
  257. , '</ul>'].join("");
  258. this.treeMenu = $(menuStr);
  259. $(this.elem).on("contextmenu", ".eleTree-node-content", function (e) {
  260. if ($(this).find(".eleTree-node-content-btn").length > 0) {
  261. ;
  262. return true
  263. }
  264. var _self = this;
  265. e.stopPropagation();
  266. e.preventDefault();
  267. // 添加active背景
  268. $(".eleTree-node-content").removeClass("eleTree-node-content-active");
  269. if (self.prevClickEle) self.prevClickEle.removeClass("eleTree-node-content-active");
  270. $(this).addClass("eleTree-node-content-active");
  271. // 菜单位置
  272. $(self.elem).after(self.treeMenu);
  273. $("#tree-menu").css({
  274. left: e.pageX + 10,
  275. top: e.pageY - 30,
  276. }).show();
  277. // 复制
  278. $("#tree-menu li.copy").off().on("click", function () {
  279. var el = $(_self).children(".eleTree-node-content-label").get(0);
  280. var selection = window.getSelection();
  281. var range = document.createRange();
  282. range.selectNodeContents(el);
  283. selection.removeAllRanges();
  284. selection.addRange(range);
  285. document.execCommand('Copy', 'false', null);
  286. selection.removeAllRanges();
  287. });
  288. // 新增
  289. $("#tree-menu li.add").off().on("click", function () {
  290. var node = $(_self).parent(".eleTree-node ");
  291. var data = self.reInitData(node);
  292. var d = data.parentData.data;
  293. // 数据返回
  294. layui.event.call(_self, "eleTree", 'add(' + self.filter + ')', {
  295. data: data.currentData,
  296. parentData: d
  297. });
  298. });
  299. // 删除
  300. $("#tree-menu li.remove").off().on("click", function () {
  301. // 数据删除
  302. var node = $(_self).parent(".eleTree-node ");
  303. var data = self.reInitData(node);
  304. var d = data.parentData.data;
  305. var arr = data.index;
  306. console.log(data)
  307. // 最外层判断
  308. if (arr.length === 1) {
  309. self.data.splice(arr[arr.length - 1], 1);
  310. } else {
  311. if (d["children"]) {
  312. d["children"].splice(arr[arr.length - 1], 1);
  313. d["children"].length === 0 && delete d["children"];
  314. }
  315. }
  316. // 数据返回
  317. layui.event.call(_self, "eleTree", 'remove(' + self.filter + ')', {
  318. data: data.currentData
  319. , parentData: d
  320. });
  321. // dom删除
  322. var tem = $(_self).parent(".eleTree-node").parent(".eleTree-node-group");
  323. //$(_self).parent(".eleTree-node").remove();
  324. var isLeaf = tem.children(".eleTree-node").length === 0;
  325. isLeaf && tem.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children("i").css("color", "transparent").removeClass("icon-rotate");
  326. });
  327. // 禁用
  328. $("#tree-menu li.forbid").off().on("click", function () {
  329. // 数据删除
  330. var node = $(_self).parent(".eleTree-node ");
  331. var data = self.reInitData(node);
  332. var d = data.parentData.data;
  333. var arr = data.index;
  334. // 最外层判断
  335. if (arr.length === 1) {
  336. self.data.splice(arr[arr.length - 1], 1);
  337. } else {
  338. if (d["children"]) {
  339. d["children"].splice(arr[arr.length - 1], 1);
  340. d["children"].length === 0 && delete d["children"];
  341. }
  342. }
  343. // 数据返回
  344. layui.event.call(_self, "eleTree", 'forbid(' + self.filter + ')', {
  345. data: data.currentData,
  346. parentData: d
  347. });
  348. // dom禁止
  349. var tem = $(_self).parent(".eleTree-node").parent(".eleTree-node-group");
  350. var isLeaf = tem.children(".eleTree-node").length === 0;
  351. isLeaf && tem.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children("i").css("color", "transparent").removeClass("icon-rotate");
  352. });
  353. self.prevClickEle = $(this);
  354. })
  355. },
  356. // 自定义checkbox解析
  357. checkboxRender: function () {
  358. $(this.elem).find(this.elem + " .eleTree-checkbox").remove();
  359. $(this.elem + " input.eleTree-hideen[type=checkbox]").each(function (index, item) {
  360. if ($(item).hasClass("eleTree-disabled")) {
  361. $(item).after('<div class="eleTree-checkbox eleTree-checkbox-disabled"><i class="layui-icon"></i></div>');
  362. } else {
  363. $(item).after('<div class="eleTree-checkbox"><i class="layui-icon"></i></div>');
  364. }
  365. })
  366. },
  367. // 通过子孙选中祖父(递归)
  368. selectParents: function (inp, eleNode, siblingNode) {
  369. // inp: 实际input(dom元素)
  370. // eleNode: input父层类(.eleTree-node)
  371. // siblingNode: 父层同级兄弟
  372. while (Number(eleNode.attr("eletree-floor")) !== 0) {
  373. // 同级input状态存入数组
  374. var arr = [];
  375. arr.push($(inp).attr("eleTree-status"));
  376. siblingNode.each(function (index, item) {
  377. var siblingIsChecked = $(item).children(".eleTree-node-content").children("input[name='eleTree-node']").attr("eleTree-status");
  378. arr.push(siblingIsChecked);
  379. })
  380. // 父元素的实际input
  381. var parentInput = eleNode.parent(".eleTree-node-group").siblings(".eleTree-node-content").children("input[name='eleTree-node']");
  382. // 父元素的checkbox替代
  383. var parentCheckbox = parentInput.siblings(".eleTree-checkbox");
  384. // 父元素的icon
  385. var parentIcon = parentCheckbox.children("i");
  386. if (arr.every(function (val) {
  387. return val === "1";
  388. })) {
  389. // 子都选中则选中父
  390. parentInput.prop("checked", "checked").attr("eleTree-status", "1");
  391. parentCheckbox.addClass("eleTree-checkbox-checked");
  392. parentIcon.addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  393. }
  394. if (arr.some(function (val) {
  395. return val === "0" || val === "2";
  396. })) {
  397. // 子有一个未选中则checkbox第三种状态
  398. // parentInput.prop("checked","checked");
  399. parentInput.attr("eleTree-status", "2");
  400. parentCheckbox.addClass("eleTree-checkbox-checked");
  401. parentIcon.removeClass("layui-icon-ok").addClass("eleTree-checkbox-line");
  402. }
  403. if (arr.every(function (val) {
  404. return val === "0";
  405. })) {
  406. // 子全部未选中则取消父选中(并且取消第三种状态)
  407. parentInput.removeAttr("checked");
  408. parentInput.attr("eleTree-status", "0");
  409. parentCheckbox.removeClass("eleTree-checkbox-checked");
  410. parentIcon.removeClass("layui-icon-ok eleTree-checkbox-line");
  411. }
  412. var parentNode = eleNode.parents("[eletree-floor='" + (Number(eleNode.attr("eletree-floor")) - 1) + "']");
  413. var parentCheckbox = parentNode.children(".eleTree-node-content").children("input[name='eleTree-node']").get(0);
  414. var parentSiblingNode = parentNode.siblings(".eleTree-node");
  415. eleNode = parentNode;
  416. inp = parentCheckbox;
  417. siblingNode = parentSiblingNode;
  418. }
  419. },
  420. // checkbox添加选中事件
  421. checkboxEvent: function () {
  422. var self = this;
  423. this.checkboxRender();
  424. // input添加属性eleTree-status:即input的三种状态,"0":未选中,"1":选中,"2":子孙部分选中
  425. $(this.elem).on("click", ".eleTree-checkbox", function (e) {
  426. e.stopPropagation();
  427. if ($(this).hasClass("eleTree-checkbox-disabled")) return;
  428. // 获取点击所在数据
  429. var node = $(this).parent(".eleTree-node-content").parent(".eleTree-node ");
  430. var d = self.reInitData(node).currentData;
  431. // 实际的input
  432. var inp = $(this).siblings(".eleTree-hideen").get(0);
  433. if (inp.checked) {
  434. $(inp).removeAttr("checked").attr("eleTree-status", "0");
  435. $(this).removeClass("eleTree-checkbox-checked");
  436. $(this).children("i").removeClass("layui-icon-ok eleTree-checkbox-line");
  437. // 数据更新
  438. delete d.checked;
  439. } else {
  440. $(inp).prop("checked", "checked").attr("eleTree-status", "1");
  441. $(this).addClass("eleTree-checkbox-checked");
  442. $(this).children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  443. d.checked = true;
  444. }
  445. var childNode = $(inp).parent(".eleTree-node-content").siblings(".eleTree-node-group").find("input[name='eleTree-node']");
  446. // 点击祖父层选中子孙层
  447. inp.checked ? (function () {
  448. childNode.prop("checked", "checked").attr("eleTree-status", "1");
  449. childNode.siblings(".eleTree-checkbox").addClass("eleTree-checkbox-checked");
  450. childNode.siblings(".eleTree-checkbox").children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  451. })() : (function () {
  452. childNode.removeAttr("checked");
  453. childNode.attr("eleTree-status", "0");
  454. childNode.siblings(".eleTree-checkbox").removeClass("eleTree-checkbox-checked");
  455. childNode.siblings(".eleTree-checkbox").children("i").removeClass("layui-icon-ok eleTree-checkbox-line");
  456. })();
  457. var eleNode = $(inp).parent(".eleTree-node-content").parent(".eleTree-node");
  458. var siblingNode = eleNode.siblings(".eleTree-node");
  459. // 点击子孙层选中祖父层(递归)
  460. self.selectParents(inp, eleNode, siblingNode);
  461. // 更新选中的数据
  462. self.getCheckedData();
  463. // 数据返回
  464. layui.event.call(inp, "eleTree", 'checkbox(' + self.filter + ')', {
  465. data: self.data
  466. , checkedData: self.checkedData
  467. , currentData: d
  468. });
  469. })
  470. },
  471. // 拖拽
  472. nodeDrag: function () {
  473. var self = this;
  474. $(this.elem).on("mousedown", ".eleTree-node-content", function (e) {
  475. var _self = this;
  476. var time = 0;
  477. e.stopPropagation();
  478. $(self.elem).css("user-select", "none");
  479. var node = $(this).parent(".eleTree-node ");
  480. var cloneNode = node.clone(true);
  481. var temNode = node.clone(true);
  482. var x = e.clientX - $(self.elem).offset().left;
  483. var y = e.clientY - $(self.elem).offset().top;
  484. $(self.elem).append(cloneNode);
  485. cloneNode.css({
  486. display: "none",
  487. position: "absolute",
  488. "background-color": "#f5f5f5",
  489. width: "100%"
  490. })
  491. $("#tree-menu").hide().remove();
  492. $(document.body).on("mousemove", function (e) {
  493. // t为了区别click事件
  494. time++;
  495. if (time > 2) {
  496. var xx = e.clientX - $(self.elem).offset().left + 10;
  497. var yy = e.clientY - $(self.elem).offset().top - 5;
  498. cloneNode.css({
  499. display: "block",
  500. left: xx + "px",
  501. top: yy + "px"
  502. })
  503. }
  504. }).on("mouseup", function (e) {
  505. // dom更改
  506. var groupNode = node.parent(".eleTree-node-group");
  507. cloneNode.remove();
  508. $(self.elem).css("user-select", "auto");
  509. $(document.body).off("mousemove").off("mouseup");
  510. var target = $(e.target);
  511. // 数据更改
  512. var dataReset = function (len, childIndex, t) {
  513. // 删除数据
  514. var d = self.reInitData(node);
  515. var parentData = d.parentData.data;
  516. var temData = d.currentData;
  517. var i = d.parentData.childIndex;
  518. if (len === 0) {
  519. // 判断目标是否超出范围
  520. return false;
  521. }
  522. // 判断当前是否是最外层
  523. if (d.index.length === 1) {
  524. self.data.splice(d.index[0], 1);
  525. } else {
  526. parentData.children.splice(i, 1);
  527. parentData.children.length === 0 && delete parentData.children;
  528. }
  529. // 如果是同级的,并且从上面的移动到下面,则index减一
  530. var f1 = Number(node.attr("eletree-floor")) - 1;
  531. var f2 = Number(node.attr("eletree-floor")) - 1;
  532. if (i < childIndex && node.parents(".eleTree-node[eletree-floor='" + f1 + "']").get(0).isEqualNode(t.parents(".eleTree-node[eletree-floor='" + f2 + "']").get(0))) {
  533. childIndex = childIndex - 1;
  534. }
  535. return {
  536. temData: temData,
  537. childIndex: childIndex
  538. };
  539. }
  540. // 判断是否是同一个dom树
  541. var isOwnTarget = target.parents(".eleTree").length === 0 ? target.get(0) : target.parents(".eleTree").get(0);
  542. if (!(isOwnTarget.isEqualNode($(self.elem + ".eleTree").get(0)))) {
  543. return;
  544. }
  545. // 判断目标是否是最外层
  546. if (target.get(0).isEqualNode($(self.elem + ".eleTree").get(0))) {
  547. var dataRe = dataReset();
  548. var d = dataRe.temData;
  549. self.data.push(d);
  550. node.remove();
  551. // 添加节点
  552. $(self.elem + ".eleTree").append(temNode);
  553. // 改floor
  554. temNode.attr("eletree-floor", "0");
  555. // 加padding
  556. temNode.children(".eleTree-node-content").css("padding-left", "0px");
  557. // 原dom去三角
  558. var leaf = groupNode.children(".eleTree-node").length === 0;
  559. leaf && groupNode.siblings(".eleTree-node-content")
  560. .children(".eleTree-node-content-icon").children(".layui-icon-triangle-r")
  561. .removeClass("icon-rotate").css("color", "transparent");
  562. // 数据返回
  563. if (time > 2) {
  564. layui.event.call(_self, "eleTree", 'drag(' + self.filter + ')', {
  565. data: self.data
  566. , currentData: d
  567. });
  568. eleTree.reload(self.elem, { data: self.data });
  569. }
  570. return;
  571. }
  572. // 判断是否不是同一个dom节点或者是其子节点(父节点不能放到子节点)
  573. var t = target;
  574. if (!target.hasClass("eleTree-node-content")) {
  575. t = target.parents(".eleTree-node-content");
  576. }
  577. var f = Number(node.attr("eletree-floor"));
  578. var isNotParentsNode = node.get(0).isEqualNode(t.parents("[eletree-floor='" + f + "']").get(0));
  579. if (!isNotParentsNode) {
  580. var d = self.reInitData(t.parent(".eleTree-node"));
  581. var i = d.parentData.childIndex;
  582. var dataRe = dataReset(d.index.length, i, t);
  583. var temData = dataRe.temData;
  584. i = dataRe.childIndex;
  585. // 判断目标是否超出范围
  586. if (temData) {
  587. node.remove();
  588. // 添加之前先删dom
  589. var parentData = d.parentData.data;
  590. if (d.index.length === 1) {
  591. parentData.children ? parentData.children.push(temData) : parentData.children = [temData];
  592. } else {
  593. parentData.children[i].children ? parentData.children[i].children.push(temData) : parentData.children[i].children = [temData];
  594. }
  595. // 添加节点
  596. target.siblings(".eleTree-node-group").append(temNode);
  597. // 改floor
  598. var floor = Number(target.parent(".eleTree-node").attr("eletree-floor")) + 1;
  599. temNode.attr("eletree-floor", String(floor));
  600. // 加padding
  601. temNode.children(".eleTree-node-content").css("padding-left", floor * 18 + "px");
  602. // 加三角
  603. target.children(".eleTree-node-content-icon").children(".layui-icon-triangle-r")
  604. .addClass("icon-rotate").css("color", "#c0c4cc");
  605. // 原dom去三角
  606. var leaf = groupNode.children(".eleTree-node").length === 0;
  607. leaf && groupNode.siblings(".eleTree-node-content")
  608. .children(".eleTree-node-content-icon").children(".layui-icon-triangle-r")
  609. .removeClass("icon-rotate").css("color", "transparent");
  610. // 数据返回
  611. if (time > 2) {
  612. layui.event.call(_self, "eleTree", 'drag(' + self.filter + ')', {
  613. data: self.data
  614. , currentData: temData
  615. , targetData: d.currentData
  616. });
  617. eleTree.reload(self.elem, { data: self.data });
  618. }
  619. }
  620. }
  621. })
  622. })
  623. },
  624. // 初始化checkbox选中状态
  625. checkInit: function (arr, floor) {
  626. var self = this;
  627. $(self.elem + " input[eleTree-status='1']").each(function (index, item) {
  628. var checkboxEl = $(item).siblings(".eleTree-checkbox");
  629. var childNode = checkboxEl.parent(".eleTree-node-content").siblings(".eleTree-node-group").find("input[name='eleTree-node']");
  630. // 选择当前
  631. checkboxEl.addClass("eleTree-checkbox-checked");
  632. checkboxEl.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  633. // 选择子孙
  634. childNode.prop("checked", "checked").attr("eleTree-status", "1");
  635. childNode.siblings(".eleTree-checkbox").addClass("eleTree-checkbox-checked");
  636. childNode.siblings(".eleTree-checkbox").children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
  637. // 选择祖父
  638. var eleNode = checkboxEl.parent(".eleTree-node-content").parent(".eleTree-node");
  639. var siblingNode = eleNode.siblings(".eleTree-node");
  640. self.selectParents(item, eleNode, siblingNode);
  641. })
  642. },
  643. // 获取选中的数据
  644. getCheckedData: function () {
  645. this.checkedData = [];
  646. var self = this;
  647. $(this.elem + " input[eletree-status='1']").each(function (index, item) {
  648. var node = $(item).parent(".eleTree-node-content").parent(".eleTree-node ");
  649. var d = self.reInitData(node).currentData;
  650. self.checkedData.push(d);
  651. });
  652. return this.checkedData
  653. },
  654. // 通过dom节点找对应数据
  655. reInitData: function (node) {
  656. var i = node.index();
  657. var floor = Number(node.attr("eletree-floor"));
  658. var arr = []; // 节点对应的index
  659. while (floor >= 0) {
  660. arr.push(i);
  661. floor = floor - 1;
  662. node = node.parents("[eletree-floor='" + floor + "']");
  663. i = node.index();
  664. }
  665. arr = arr.reverse();
  666. var oData = this.data;
  667. // 当前节点的父节点数据
  668. var parentData = oData[arr[0]];
  669. // 当前节点的data数据
  670. var d = oData[arr[0]];
  671. for (var i = 1; i < arr.length; i++) {
  672. d = d["children"] ? d["children"][arr[i]] : d;
  673. }
  674. for (var i = 1; i < arr.length - 1; i++) {
  675. parentData = parentData["children"] ? parentData["children"][arr[i]] : parentData;
  676. }
  677. return {
  678. currentData: d,
  679. parentData: {
  680. data: parentData,
  681. childIndex: arr[arr.length - 1]
  682. },
  683. index: arr
  684. }
  685. },
  686. }
  687. var thisEleTree = function () {
  688. thisEleTree.o[this.elem] = this;
  689. thisEleTree.config[this.elem] = this.option;
  690. thisEleTree.getCheckedData[this.elem] = this.getCheckedData;
  691. }
  692. // 保存当前对象(为了获取选中元素时改变this指向)
  693. thisEleTree.o = {};
  694. // 保存对象的option
  695. thisEleTree.config = {};
  696. // 获取选中的元素
  697. thisEleTree.getCheckedData = {};
  698. var eleTree = {
  699. checkedData: function (elem) {
  700. return thisEleTree.getCheckedData[elem].call(thisEleTree.o[elem]);
  701. },
  702. render: function (option) {
  703. var inst = new Class(option);
  704. thisEleTree.call(inst);
  705. },
  706. on: function (events, callback) {
  707. return layui.onevent.call(this, "eleTree", events, callback);
  708. },
  709. reload: function (elem, option) {
  710. var config = thisEleTree.config[elem];
  711. this.render($.extend({}, config, option));
  712. }
  713. }
  714. exports('eleTree', eleTree);
  715. })