layui-xtree.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. //**********************************
  2. //** 本插件依赖 贤心 layui form模块
  3. //** 由 小巷 制作 QQ:151446298
  4. //** 版本3.0 时间 2018-01-10 20:48
  5. //**********************************
  6. //构造
  7. function layuiXtree(options) {
  8. var _this = this;
  9. _this._containerid = options.elem;
  10. _this.tool = options.tool;
  11. _this.checkbox = options.checkbox;
  12. typeof options.toolbar == 'function' && (_this.toolbar = options.toolbar);
  13. _this._container = document.getElementById(options.elem); //容器
  14. _this._container.style.minHeight = "100px";
  15. _this._options = options;
  16. _this.Loading(options);
  17. }
  18. //封装IE8 Class选择
  19. layuiXtree.prototype.getByClassName = function (cn) {
  20. if (document.getElementsByClassName) return this._container.getElementsByClassName(cn);
  21. var _xlist = this._container.childNodes;
  22. var _xtemp = new Array();
  23. for (var i = 0; i < _xlist.length; i++) {
  24. var _xchild = _xlist[i];
  25. var _xclassNames = _xchild.getAttribute('class').split(' ');
  26. for (var j = 0; j < _xclassNames.length; j++) {
  27. if (_xclassNames[j] == cn) {
  28. _xtemp.push(_xchild);
  29. break;
  30. }
  31. }
  32. }
  33. return _xtemp;
  34. }
  35. //在一个对象下面找子级
  36. layuiXtree.prototype.getChildByClassName = function (obj, cn) {
  37. var _xlist = obj.childNodes;
  38. var _xtemp = new Array();
  39. for (var i = 0; i < _xlist.length; i++) {
  40. var _xchild = _xlist[i];
  41. var _xclassNames = _xchild.getAttribute('class').split(' ');
  42. for (var j = 0; j < _xclassNames.length; j++) {
  43. if (_xclassNames[j] == cn) {
  44. _xtemp.push(_xchild);
  45. break;
  46. }
  47. }
  48. }
  49. return _xtemp;
  50. }
  51. //加载特效,且获取数据
  52. layuiXtree.prototype.Loading = function (options) {
  53. var _this = this;
  54. _this.xloading = document.createElement("span"); //创建加载对象
  55. _this.xloading.setAttribute('class', 'layui-icon layui-anim layui-anim-rotate layui-anim-loop');
  56. _this.xloading.innerHTML = '&#xe63e;';
  57. _this.xloading.style.fontSize = "50px";
  58. _this.xloading.style.color = "#009688";
  59. _this.xloading.style.fontWeight = "bold";
  60. _this.xloading.style.marginLeft = _this._container.offsetWidth / 2 - 25 + 'px';
  61. _this.xloading.style.marginTop = _this._container.offsetHeight / 2 - 50 + 'px';
  62. _this._container.innerHTML = '';
  63. _this._container.appendChild(_this.xloading); //加载显示
  64. if (typeof (options.data) == 'object') {
  65. _this._dataJson = options.data;
  66. _this.Initial(options);
  67. return;
  68. }
  69. //如果是字符串url,进行异步加载
  70. var obj = new XMLHttpRequest();
  71. obj.onreadystatechange = function () {
  72. if (obj.readyState == 4 && obj.status == 200 || obj.status == 304) { //回调成功
  73. if (JSON.parse(obj.responseText).data) {
  74. _this._dataJson = eval('(' + obj.responseText + ')').data;
  75. //_this._dataJson = eval('(' + JSON.parse(obj.responseText).menu + ')'); //将返回的数据转为json
  76. }
  77. _this.Initial(options);
  78. }
  79. };
  80. obj.open('get', options.data, true);
  81. obj.send();
  82. }
  83. //data验证后的数据初始化
  84. layuiXtree.prototype.Initial = function (o) {
  85. var _this = this;
  86. _this._form = o.form; //layui from对象
  87. _this.checkedName = o.checkedName || 'roleId';
  88. _this._domStr = ""; //结构字符串
  89. _this._isopen = o.isopen != null ? o.isopen : true;
  90. if (o.color == null) o.color = {
  91. open: '#2F4056',
  92. close: '#2F4056',
  93. end: '#2F4056'
  94. }; //图标颜色
  95. _this._iconOpenColor = o.color.open != null ? o.color.open : "#2F4056";
  96. _this._iconCloseColor = o.color.close != null ? o.color.close : "#2F4056";
  97. _this._iconEndColor = o.color.end != null ? o.color.end : "#2F4056";
  98. if (o.icon == null) o.icon = {
  99. open: '&#xe625;',
  100. close: '&#xe623;',
  101. end: '&#xe621;'
  102. }; //图标样式
  103. _this._iconOpen = o.icon.open != null ? o.icon.open : '&#xe625;';
  104. _this._iconClose = o.icon.close != null ? o.icon.close : '&#xe623;';
  105. _this._iconEnd = o.icon.end != null ? o.icon.end : '&#xe621;';
  106. _this._click = o.click != null ? o.click : function () {};
  107. _this._ckall = o.ckall != null ? o.ckall : false; //全选是否启用
  108. _this._ckallSuccess = o.ckallback != null ? o.ckallback : function () {}; //全选回调
  109. _this.CreateCkAll();
  110. _this.dataBind(_this._dataJson);
  111. _this.Rendering();
  112. }
  113. //全选框
  114. layuiXtree.prototype.CreateCkAll = function () {
  115. var _this = this;
  116. if (_this._ckall) {
  117. _this._domStr += '<div class="layui-xtree-item">';
  118. _this._domStr +=
  119. '<input type="checkbox" class="layui-xtree-checkbox layui-xtree-ckall" title="全选" lay-skin="primary" lay-filter="xtreeckall' +
  120. _this._containerid + '">';
  121. _this._domStr += '</div>';
  122. }
  123. }
  124. //生产结构
  125. layuiXtree.prototype.dataBind = function (d) {
  126. var _this = this;
  127. if (d.length > 0) {
  128. for (i in d) {
  129. var xtree_isend = '';
  130. var xtree_ischecked = '';
  131. var xtree_isdisabled = d[i].disabled ? ' disabled="disabled" ' : '';
  132. _this._domStr += '<div class="layui-xtree-item">';
  133. if (!d[i].childMenus) {
  134. d[i].childMenus = [];
  135. }
  136. if (d[i].childMenus.length > 0)
  137. _this._domStr += '<i class="layui-icon layui-xtree-icon" data-xtree="' + (_this._isopen ? '1' : '0') +
  138. '">' + (_this._isopen ? _this._iconOpen : _this._iconClose) + '</i>';
  139. else {
  140. _this._domStr += '<i class="layui-icon layui-xtree-icon-null">' + (d[i].icon || _this._iconEnd) +
  141. '</i>';
  142. xtree_isend = 'data-xend="1"';
  143. xtree_ischecked = !!d[i][_this.checkedName] ? ' checked ' : '';
  144. xtree_isdisabled = d[i].disabled ? ' disabled="disabled" ' : '';
  145. }
  146. if (!!_this.checkbox) {
  147. _this._domStr += '<input type="checkbox" class="layui-xtree-checkbox" ' + xtree_isend +
  148. xtree_ischecked +
  149. xtree_isdisabled + ' value="' + d[i].id + '" title="' + d[i].name +
  150. '" lay-skin="primary" lay-filter="xtreeck' + _this._containerid + '">';
  151. }else{
  152. _this._domStr += '<div class="layui-inline" style="margin-top: 10px;margin-bottom:0;"><span>'+d[i].name+'</span></div>';
  153. }
  154. if (!!_this.tool) {
  155. _this._domStr +=
  156. '<div class="layui-inline" style="margin-top: 10px;margin-bottom:0;"><a class="layui-btn layui-btn-xs" name="tree_event" event="edit"id="' +
  157. d[i].id +
  158. '">修改</a><a class="layui-btn layui-btn-danger layui-btn-xs" name="tree_event" event="del" id="' +
  159. d[i].id + '">删除</a></div>';
  160. }
  161. _this.dataBind(d[i].childMenus);
  162. _this._domStr += '</div>';
  163. }
  164. }
  165. }
  166. //工具栏监听回调
  167. layuiXtree.prototype.toolbar = function (obj) {
  168. }
  169. //通过ID获取
  170. layuiXtree.prototype.idGetObj = function (id) {
  171. var _this = this;
  172. var obj = {};
  173. (function get(d) {
  174. if (d.length > 0) {
  175. for (i in d) {
  176. if (!d[i].childMenus) {
  177. d[i].childMenus = [];
  178. }
  179. if (d[i].id == id) {
  180. obj = d[i];
  181. }
  182. get(d[i].childMenus);
  183. }
  184. }
  185. })(_this._dataJson);
  186. return obj;
  187. }
  188. //渲染呈现
  189. layuiXtree.prototype.Rendering = function () {
  190. var _this = this;
  191. _this._container.innerHTML = _this._domStr;
  192. _this._domStr = "";
  193. //检查选中状态
  194. var xtree_ckitems = _this.getByClassName('layui-xtree-checkbox');
  195. for (var i = 0; i < xtree_ckitems.length; i++) {
  196. if (xtree_ckitems[i].getAttribute('data-xend') == '1' && xtree_ckitems[i].checked) {
  197. _this.ParentCheckboxChecked(xtree_ckitems[i]);
  198. }
  199. }
  200. _this._form.render('checkbox'); //layui渲染
  201. //绑定工具条事件
  202. var tree_event = document.getElementsByName('tree_event');
  203. for (var tr_i in tree_event) {
  204. tree_event[tr_i].onclick = function (e) {
  205. _this.toolbar({
  206. event: this.getAttribute('event'),
  207. data: _this.idGetObj(this.id)
  208. });
  209. };
  210. }
  211. var xtree_items = _this.getByClassName('layui-xtree-item');
  212. var xtree_icons = _this.getByClassName('layui-xtree-icon');
  213. var xtree_nullicons = _this.getByClassName('layui-xtree-icon-null');
  214. for (var i = 0; i < xtree_items.length; i++) {
  215. if (xtree_items[i].parentNode == _this._container)
  216. xtree_items[i].style.margin = '5px 0 0 10px';
  217. else {
  218. xtree_items[i].style.margin = '5px 0 0 45px';
  219. if (!_this._isopen) xtree_items[i].style.display = 'none';
  220. }
  221. }
  222. for (var i = 0; i < xtree_icons.length; i++) {
  223. xtree_icons[i].style.position = "relative";
  224. xtree_icons[i].style.top = "3px";
  225. xtree_icons[i].style.margin = "0 5px 0 0";
  226. xtree_icons[i].style.fontSize = "18px";
  227. xtree_icons[i].style.color = _this._isopen ? _this._iconOpenColor : _this._iconCloseColor;
  228. xtree_icons[i].style.cursor = "pointer";
  229. xtree_icons[i].onclick = function () {
  230. var xtree_chi = this.parentNode.childNodes;
  231. if (this.getAttribute('data-xtree') == 1) {
  232. for (var j = 0; j < xtree_chi.length; j++) {
  233. if (xtree_chi[j].getAttribute('class') == 'layui-xtree-item')
  234. xtree_chi[j].style.display = 'none';
  235. }
  236. this.setAttribute('data-xtree', '0')
  237. this.innerHTML = _this._iconClose;
  238. this.style.color = _this._iconCloseColor;
  239. } else {
  240. for (var j = 0; j < xtree_chi.length; j++) {
  241. if (xtree_chi[j].getAttribute('class') == 'layui-xtree-item')
  242. xtree_chi[j].style.display = 'block';
  243. }
  244. this.setAttribute('data-xtree', '1')
  245. this.innerHTML = _this._iconOpen;
  246. this.style.color = _this._iconOpenColor;
  247. }
  248. }
  249. }
  250. for (var i = 0; i < xtree_nullicons.length; i++) {
  251. xtree_nullicons[i].style.position = "relative";
  252. xtree_nullicons[i].style.top = "6px";
  253. xtree_nullicons[i].style.margin = "0 5px 0 0";
  254. xtree_nullicons[i].style.fontSize = "18px";
  255. xtree_nullicons[i].style.color = _this._iconEndColor;
  256. }
  257. _this._form.on('checkbox(xtreeck' + _this._containerid + ')', function (da) {
  258. //获取当前点击复选框的容器下面的所有子级容器
  259. var xtree_chis = da.elem.parentNode.getElementsByClassName('layui-xtree-item');
  260. //遍历它们,选中状态与它们的父级一致(类似全选功能)
  261. for (var i = 0; i < xtree_chis.length; i++) {
  262. if (!_this.getChildByClassName(xtree_chis[i], 'layui-xtree-checkbox')[0].disabled) {
  263. _this.getChildByClassName(xtree_chis[i], 'layui-xtree-checkbox')[0].checked = da.elem.checked;
  264. if (da.elem.checked) _this.getChildByClassName(xtree_chis[i], 'layui-xtree-checkbox')[0].nextSibling
  265. .classList.add('layui-form-checked');
  266. else _this.getChildByClassName(xtree_chis[i], 'layui-xtree-checkbox')[0].nextSibling.classList
  267. .remove('layui-form-checked');
  268. }
  269. }
  270. _this.ParendCheck(da.elem);
  271. _this._click(da);
  272. });
  273. var _xtree_disableds = _this.getByClassName('layui-disabled');
  274. for (var i = 0; i < _xtree_disableds.length; i++) {
  275. _xtree_disableds[i].getElementsByTagName('span')[0].style.color = "#B5B5B5";
  276. }
  277. //全选按钮
  278. if (_this._ckall) {
  279. _this._form.on('checkbox(xtreeckall' + _this._containerid + ')', function (data) {
  280. var xtree_allck = data.elem.parentNode.parentNode.getElementsByClassName('layui-form-checkbox');
  281. for (var i = 0; i < xtree_allck.length; i++) {
  282. if (xtree_allck[i].getAttribute('class').indexOf('layui-checkbox-disbaled') == -1) {
  283. if (data.elem.checked) {
  284. xtree_allck[i].classList.add('layui-form-checked');
  285. } else {
  286. xtree_allck[i].classList.remove('layui-form-checked');
  287. }
  288. xtree_allck[i].parentNode.getElementsByClassName('layui-xtree-checkbox')[0].checked =
  289. data.elem.checked;
  290. }
  291. }
  292. _this._ckallSuccess();
  293. });
  294. }
  295. }
  296. //更新渲染
  297. layuiXtree.prototype.render = function () {
  298. var _this = this;
  299. _this.Loading(_this._options);
  300. }
  301. //子节点选中改变,父节点更改自身状态
  302. layuiXtree.prototype.ParendCheck = function (ckelem) {
  303. var _this = this;
  304. var xtree_p = ckelem.parentNode.parentNode;
  305. if (xtree_p.getAttribute('class') == 'layui-xtree-item') {
  306. var xtree_all = _this.getChildByClassName(xtree_p, 'layui-xtree-item');
  307. var xtree_count = 0;
  308. for (var i = 0; i < xtree_all.length; i++) {
  309. if (_this.getChildByClassName(xtree_all[i], 'layui-xtree-checkbox')[0].checked) {
  310. xtree_count++;
  311. }
  312. }
  313. if (xtree_count <= 0) {
  314. _this.getChildByClassName(xtree_p, 'layui-xtree-checkbox')[0].checked = false;
  315. _this.getChildByClassName(xtree_p, 'layui-xtree-checkbox')[0].nextSibling.classList.remove(
  316. 'layui-form-checked');
  317. } else {
  318. _this.getChildByClassName(xtree_p, 'layui-xtree-checkbox')[0].checked = true;
  319. _this.getChildByClassName(xtree_p, 'layui-xtree-checkbox')[0].nextSibling.classList.add(
  320. 'layui-form-checked');
  321. }
  322. this.ParendCheck(_this.getChildByClassName(xtree_p, 'layui-xtree-checkbox')[0]);
  323. }
  324. }
  325. //渲染之前按照选中的末级去改变父级选中状态
  326. layuiXtree.prototype.ParentCheckboxChecked = function (e) {
  327. var _this = this;
  328. if (e.parentNode.parentNode.getAttribute('class') == 'layui-xtree-item') {
  329. var _pe = _this.getChildByClassName(e.parentNode.parentNode, 'layui-xtree-checkbox')[0];
  330. _pe.checked = true;
  331. _this.ParentCheckboxChecked(_pe);
  332. }
  333. }
  334. //获取全部选中的末级checkbox对象
  335. layuiXtree.prototype.GetChecked = function () {
  336. var _this = this;
  337. var arr = new Array();
  338. var arrIndex = 0;
  339. var cks = _this.getByClassName('layui-xtree-checkbox');
  340. for (var i = 0; i < cks.length; i++) {
  341. if (cks[i].checked && cks[i].getAttribute('data-xend') == '1') {
  342. arr[arrIndex] = cks[i];
  343. arrIndex++;
  344. }
  345. }
  346. return arr;
  347. }
  348. //获取全部选中的checkbox对象value
  349. layuiXtree.prototype.GetCheckedVal = function () {
  350. var _this = this;
  351. var arr = new Array();
  352. var arrIndex = 0;
  353. var cks = _this.getByClassName('layui-xtree-checkbox');
  354. for (var i = 0; i < cks.length; i++) {
  355. if (cks[i].checked) {
  356. arr[arrIndex] = cks[i].value;
  357. arrIndex++;
  358. }
  359. }
  360. return arr;
  361. }
  362. //获取全部的原始checkbox对象
  363. layuiXtree.prototype.GetAllCheckBox = function () {
  364. var _this = this;
  365. var arr = new Array();
  366. var arrIndex = 0;
  367. var cks = _this.getByClassName('layui-xtree-checkbox');
  368. for (var i = 0; i < cks.length; i++) {
  369. arr[arrIndex] = cks[i];
  370. arrIndex++;
  371. }
  372. return arr;
  373. }
  374. //根据值来获取其父级的checkbox原dom对象
  375. layuiXtree.prototype.GetParent = function (a) {
  376. var _this = this;
  377. var cks = _this.getByClassName('layui-xtree-checkbox');
  378. for (var i = 0; i < cks.length; i++) {
  379. if (cks[i].value == a) {
  380. if (cks[i].parentNode.parentNode.getAttribute('id') == _this._container.getAttribute('id')) return null;
  381. return _this.getChildByClassName(cks[i].parentNode.parentNode, 'layui-xtree-checkbox')[0];
  382. }
  383. }
  384. return null;
  385. }