grid-extend.js 12 KB

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