grid-extend.js 11 KB

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