grid-extend.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. (function (w, $) {
  2. function Tree(opts) {
  3. this.options = $.extend({
  4. button: null,
  5. table: null,
  6. url: '',
  7. perPage: '',
  8. showNextPage: '',
  9. pageQueryName: '',
  10. parentIdQueryName: '',
  11. levelQueryName: '',
  12. showIcon: 'fa-angle-right',
  13. hideIcon: 'fa-angle-down',
  14. loadMoreText: '<svg style="fill:currentColor" t="1582877365167" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32874" width="24" height="24"><path d="M162.8 515m-98.3 0a98.3 98.3 0 1 0 196.6 0 98.3 98.3 0 1 0-196.6 0Z" p-id="32875"></path><path d="M511.9 515m-98.3 0a98.3 98.3 0 1 0 196.6 0 98.3 98.3 0 1 0-196.6 0Z" p-id="32876"></path><path d="M762.8 515a98.3 98.3 0 1 0 196.6 0 98.3 98.3 0 1 0-196.6 0Z" p-id="32877"></path></svg>',
  15. }, opts);
  16. this.key = this.level = this.row = this.data = this._req = null;
  17. this._init();
  18. }
  19. Tree.prototype = {
  20. _init: function () {
  21. this._bindClick();
  22. },
  23. _bindClick: function () {
  24. var _this = this,
  25. opts = _this.options;
  26. $(opts.button).off('click').click(function () {
  27. if (_this._req) {
  28. return;
  29. }
  30. var $this = $(this),
  31. _i = $("i", this),
  32. shown = _i.hasClass(opts.showIcon);
  33. _this.key = $this.data('key');
  34. _this.level = $this.data('level');
  35. _this.row = $this.closest('tr');
  36. if ($this.data('inserted') == '0') {
  37. _this._request(1);
  38. $this.data('inserted', 1);
  39. }
  40. _i.toggleClass(opts.showIcon + ' ' + opts.hideIcon);
  41. var children = [];
  42. getChildren(_this.row.nextAll(), _this.row).forEach(function (v) {
  43. if (! (getLevel(v) === (_this.level + 1))) {
  44. return;
  45. }
  46. children.push(v);
  47. shown ? $(v).show() : $(v).hide();
  48. });
  49. children.forEach(function (v) {
  50. if (shown) {
  51. return
  52. }
  53. var icon = $(v).find('a[data-level=' + getLevel(v) + '] i');
  54. if (icon.hasClass(opts.hideIcon)) {
  55. icon.parent().click();
  56. }
  57. })
  58. })
  59. },
  60. _request: function (page, after) {
  61. var _this = this,
  62. row = _this.row,
  63. key = _this.key,
  64. level = _this.level,
  65. tableSelector = _this.options.table;
  66. if (_this._req) {
  67. return;
  68. }
  69. _this._req = 1;
  70. LA.loading();
  71. var data = {
  72. _token: LA.token,
  73. };
  74. data[_this.options.parentIdQueryName] = key;
  75. data[_this.options.levelQueryName] = level + 1;
  76. data[_this.options.pageQueryName.replace(':key', key)] = page;
  77. $.ajax({
  78. url: _this.options.url,
  79. type: 'GET',
  80. data: data,
  81. headers: {'X-PJAX': true},
  82. success: function (resp) {
  83. after && after();
  84. LA.loading(false);
  85. _this._req = 0;
  86. // 获取最后一行
  87. var children = getChildren(row.nextAll(), row);
  88. row = children.length ? $(children.pop()) : row;
  89. var _body = $('<div>'+resp+'</div>'),
  90. _tbody = _body.find(tableSelector + ' tbody'),
  91. lastPage = _body.find('last-page').text(),
  92. nextPage = _body.find('next-page').text();
  93. // 标记子节点行
  94. _tbody.find('tr').each(function (_, v) {
  95. $(v).attr('data-level', level + 1)
  96. });
  97. if (
  98. _this.options.showNextPage
  99. && _tbody.find('tr').length == _this.options.perPage
  100. && lastPage >= page
  101. ) {
  102. // 加载更多
  103. var loadMore = $("<tr data-level='" + (level + 1) + "' data-page='" + nextPage
  104. + "'><td colspan='"+(row.find('td').length)
  105. + "' align='center' style='cursor: pointer'> <a>" + _this.options.loadMoreText + "</a> </td></tr>");
  106. row.after(loadMore);
  107. // 加载更多
  108. loadMore.click(function () {
  109. var _t = $(this);
  110. _this._request(_t.data('page'), function () {
  111. _t.remove();
  112. });
  113. });
  114. }
  115. // 附加子节点
  116. row.after(_tbody.html());
  117. // 附加子节点js脚本以及触发子节点js脚本执行
  118. _body.find('script').each(function (_, v) {
  119. row.after(v);
  120. });
  121. $(document).trigger('pjax:script')
  122. },
  123. error:function(a, b, c){
  124. after && after();
  125. LA.loading(false);
  126. _this._req = 0;
  127. if (a.status != 404) {
  128. LA.ajaxError(a, b, c);
  129. }
  130. }
  131. });
  132. }
  133. };
  134. function Orderable(opts) {
  135. this.options = $.extend({
  136. button: null,
  137. url: '',
  138. }, opts);
  139. this.direction = this.key = this.level = this.row = this._req = null;
  140. this._init();
  141. }
  142. Orderable.prototype = {
  143. _init: function () {
  144. this._bindClick()
  145. },
  146. _bindClick: function () {
  147. var _this = this;
  148. $(_this.options.button).off('click').click(function () {
  149. if (_this._req) {
  150. return;
  151. }
  152. _this._req = 1;
  153. LA.loading();
  154. var $this = $(this);
  155. _this.key = $this.data('id');
  156. _this.direction = $this.data('direction');
  157. _this.row = $this.closest('tr');
  158. _this.level = getLevel(_this.row);
  159. _this._request();
  160. })
  161. },
  162. _request: function () {
  163. var _this = this,
  164. key = _this.key,
  165. row = _this.row,
  166. level = _this.level,
  167. direction = _this.direction,
  168. prevAll = row.prevAll(),
  169. nextAll = row.nextAll(),
  170. prev = row.prevAll('tr').first(),
  171. next = row.nextAll('tr').first();
  172. $.ajax({
  173. type: 'POST',
  174. url: _this.options.url.replace(':key', key),
  175. data: {_method:'PUT', _token:LA.token, _orderable:direction},
  176. success: function(data){
  177. LA.loading(false);
  178. _this._req = 0;
  179. if (! data.status) {
  180. return data.message && LA.warning(data.message, 'rt');
  181. }
  182. LA.success(data.message);
  183. if (direction) {
  184. var prevRow = sibling(prevAll, level);
  185. if (swapable(prevRow, level) && prev.length && getLevel(prev) >= level) {
  186. prevRow.before(row);
  187. // 把所有子节点上移
  188. getChildren(nextAll, row).forEach(function (v) {
  189. prevRow.before(v)
  190. });
  191. }
  192. } else {
  193. var nextRow = sibling(nextAll, level),
  194. nextRowChildren = nextRow ? getChildren(nextRow.nextAll(), nextRow) : [];
  195. if (swapable(nextRow, level) && next.length && getLevel(next) >= level) {
  196. nextAll = row.nextAll();
  197. if (nextRowChildren.length) {
  198. nextRow = $(nextRowChildren.pop())
  199. }
  200. // 把所有子节点下移
  201. var all = [];
  202. getChildren(nextAll, row).forEach(function (v) {
  203. all.unshift(v)
  204. });
  205. all.forEach(function(v) {
  206. nextRow.after(v)
  207. });
  208. nextRow.after(row);
  209. }
  210. }
  211. },
  212. error: function (a, b, c) {
  213. _this._req = 0;
  214. LA.loading(false);
  215. LA.ajaxError(a, b, c)
  216. }
  217. });
  218. },
  219. };
  220. function isTr(v) {
  221. return $(v).prop('tagName').toLocaleLowerCase() === 'tr'
  222. }
  223. function getLevel(v) {
  224. return parseInt($(v).data('level') || 0);
  225. }
  226. function isChildren(parent, child) {
  227. return getLevel(child) > getLevel(parent);
  228. }
  229. function getChildren(all, parent) {
  230. var arr = [], isBreak = false, firstTr;
  231. all.each(function (_, v) {
  232. // 过滤非tr标签
  233. if (! isTr(v) || isBreak) return;
  234. firstTr || (firstTr = $(v));
  235. // 非连续的子节点
  236. if (firstTr && ! isChildren(parent, firstTr)) {
  237. return;
  238. }
  239. if (isChildren(parent, v)) {
  240. arr.push(v)
  241. } else {
  242. isBreak = true;
  243. }
  244. });
  245. return arr;
  246. }
  247. function swapable(_o, level) {
  248. if (
  249. _o
  250. && _o.length
  251. && level === getLevel(_o)
  252. ) {
  253. return true
  254. }
  255. }
  256. function sibling(all, level) {
  257. var next;
  258. all.each(function (_, v) {
  259. if (getLevel(v) === level && ! next && isTr(v)) {
  260. next = $(v);
  261. }
  262. });
  263. return next;
  264. }
  265. w.LA.grid.tree = function (opts) {
  266. return new Tree(opts);
  267. };
  268. w.LA.grid.orderable = function (opts) {
  269. return new Orderable(opts);
  270. };
  271. })(window, $);