TableLayout.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. define([ "require", "backbone", "hbs!tmpl/common/TableLayout_tmpl", "utils/Messages", "utils/Utils", "utils/Globals", "utils/CommonViewFunction", "backgrid-filter", "backgrid-paginator", "backgrid-sizeable", "backgrid-orderable", "backgrid-select-all", "backgrid-columnmanager" ], function(require, Backbone, FSTablelayoutTmpl, Messages, Utils, Globals, CommonViewFunction) {
  2. "use strict";
  3. var FSTableLayout = Backbone.Marionette.LayoutView.extend({
  4. _viewName: "FSTableLayout",
  5. template: FSTablelayoutTmpl,
  6. templateHelpers: function() {
  7. return this.options;
  8. },
  9. regions: {
  10. rTableList: 'div[data-id="r_tableList"]',
  11. rTableSpinner: 'div[data-id="r_tableSpinner"]',
  12. rPagination: 'div[data-id="r_pagination"]',
  13. rFooterRecords: 'div[data-id="r_footerRecords"]'
  14. },
  15. ui: {
  16. selectPageSize: 'select[data-id="pageSize"]',
  17. paginationDiv: '[data-id="paginationDiv"]',
  18. previousData: "[data-id='previousData']",
  19. nextData: "[data-id='nextData']",
  20. pageRecordText: "[data-id='pageRecordText']",
  21. showPage: "[data-id='showPage']",
  22. gotoPage: "[data-id='gotoPage']",
  23. gotoPagebtn: "[data-id='gotoPagebtn']",
  24. activePage: "[data-id='activePage']"
  25. },
  26. gridOpts: {
  27. className: "table table-bordered table-hover table-condensed backgrid",
  28. emptyText: "没有找到记录!"
  29. },
  30. filterOpts: {
  31. placeholder: "plcHldr.searchByResourcePath",
  32. wait: 150
  33. },
  34. paginatorOpts: {
  35. windowSize: 5,
  36. slideScale: .5,
  37. goBackFirstOnSort: !1
  38. },
  39. controlOpts: {
  40. rewind: null,
  41. back: {
  42. label: "<i class='fa fa-angle-left'></i>",
  43. title: "前一页"
  44. },
  45. forward: {
  46. label: "<i class='fa fa-angle-right'></i>",
  47. title: "下一页"
  48. },
  49. fastForward: null
  50. },
  51. columnOpts: {
  52. opts: {
  53. initialColumnsVisible: 4,
  54. saveState: !1,
  55. loadStateOnInit: !0
  56. },
  57. visibilityControlOpts: {},
  58. el: null
  59. },
  60. includePagination: !0,
  61. includeAtlasPagination: !1,
  62. includeAtlasPageSize: !1,
  63. includeFilter: !1,
  64. includeHeaderSearch: !1,
  65. includePageSize: !1,
  66. includeGotoPage: !1,
  67. includeFooterRecords: !0,
  68. includeColumnManager: !1,
  69. includeSizeAbleColumns: !1,
  70. includeOrderAbleColumns: !1,
  71. includeTableLoader: !0,
  72. includeAtlasTableSorting: !1,
  73. showDefaultTableSorted: !1,
  74. updateFullCollectionManually: !1,
  75. sortOpts: {
  76. sortColumn: "name",
  77. sortDirection: "ascending"
  78. },
  79. events: function() {
  80. var events = {}, that = this;
  81. return events["change " + this.ui.selectPageSize] = "onPageSizeChange", events["change " + this.ui.showPage] = "changePageLimit",
  82. events["click " + this.ui.nextData] = "onClicknextData", events["click " + this.ui.previousData] = "onClickpreviousData",
  83. events["click " + this.ui.gotoPagebtn] = "gotoPagebtn", events["keyup " + this.ui.gotoPage] = function(e) {
  84. var code = e.which;
  85. parseInt(e.currentTarget.value);
  86. e.currentTarget.value ? that.ui.gotoPagebtn.attr("disabled", !1) : that.ui.gotoPagebtn.attr("disabled", !0),
  87. 13 == code && e.currentTarget.value && that.gotoPagebtn();
  88. }, events;
  89. },
  90. initialize: function(options) {
  91. if (this.limit = 25, this.offset = 0, _.extend(this, _.omit(options, "gridOpts", "sortOpts", "atlasPaginationOpts")),
  92. _.extend(this, options.atlasPaginationOpts), _.extend(this.gridOpts, options.gridOpts, {
  93. collection: this.collection,
  94. columns: this.columns
  95. }), _.extend(this.sortOpts, options.sortOpts), this.isApiSorting && 0 === this.offset && (this.limit = this.count || this.limit),
  96. this.includeAtlasTableSorting) {
  97. var oldSortingRef = this.collection.setSorting;
  98. this.collection.setSorting = function() {
  99. this.state.pageSize = this.length;
  100. var val = oldSortingRef.apply(this, arguments);
  101. return val.fullCollection.sort(), this.comparator = function(next, previous, data) {
  102. var getValue = function(options) {
  103. var next = options.next, previous = options.previous, order = options.order;
  104. return next === previous ? null : order === -1 ? next < previous ? -1 : 1 : next < previous ? 1 : -1;
  105. }, getKeyVal = function(model, key) {
  106. var value = null;
  107. return model && key && (value = model[key], value || _.each(model, function(modalValue) {
  108. "object" == typeof modalValue && (value || (value = getKeyVal(modalValue, key)));
  109. })), Number(value) || value;
  110. };
  111. if (val.state && !_.isNull(val.state.sortKey)) {
  112. var nextValue, previousValue;
  113. return next && next.get("attributes") && next.get("attributes")[val.state.sortKey] || previous && previous.get("attributes") && previous.get("attributes")[val.state.sortKey] ? (nextValue = next.get("attributes")[val.state.sortKey],
  114. previousValue = previous.get("attributes")[val.state.sortKey]) : (nextValue = getKeyVal(next.attributes, val.state.sortKey),
  115. previousValue = getKeyVal(previous.attributes, val.state.sortKey)), nextValue = "string" == typeof nextValue ? nextValue.toLowerCase() : nextValue,
  116. previousValue = "string" == typeof previousValue ? previousValue.toLowerCase() : previousValue,
  117. getValue({
  118. next: nextValue || "",
  119. previous: previousValue || "",
  120. order: val.state.order
  121. });
  122. }
  123. }, val;
  124. };
  125. }
  126. this.bindEvents();
  127. },
  128. bindEvents: function() {
  129. this.listenTo(this.collection, "request", function() {
  130. this.$('div[data-id="r_tableSpinner"]').addClass("show");
  131. }, this), this.listenTo(this.collection, "sync error", function() {
  132. this.$('div[data-id="r_tableSpinner"]').removeClass("show");
  133. }, this), this.listenTo(this.collection, "reset", function(collection, options) {
  134. this.$('div[data-id="r_tableSpinner"]').removeClass("show"), this.ui.gotoPage.val(""),
  135. this.ui.gotoPage.parent().removeClass("has-error"), this.ui.gotoPagebtn.prop("disabled", !0),
  136. this.includePagination && this.renderPagination(), this.includeFooterRecords && this.renderFooterRecords(this.collection.state),
  137. this.includeAtlasPagination && this.renderAtlasPagination(options);
  138. }, this), this.listenTo(this.collection, "backgrid:sorted", function(column, direction, collection) {
  139. this.isApiSorting ? column.set("direction", direction) : (this.collection.fullCollection.trigger("backgrid:sorted", column, direction, collection),
  140. this.includeAtlasTableSorting && this.updateFullCollectionManually && this.collection.fullCollection.reset(collection.toJSON(), {
  141. silent: !0
  142. }));
  143. }, this), this.listenTo(this, "grid:refresh", function() {
  144. this.grid && this.grid.trigger("backgrid:refresh");
  145. }), this.listenTo(this, "grid:refresh:update", function() {
  146. this.grid && (this.grid.trigger("backgrid:refresh"), this.grid.collection && this.grid.collection.trigger("backgrid:colgroup:updated"));
  147. }), this.listenTo(this.collection, "backgrid:refresh", function() {}, this);
  148. },
  149. onRender: function() {
  150. this.renderTable(), this.includePagination && this.renderPagination(), this.includeAtlasPagination && this.renderAtlasPagination(),
  151. this.includeFilter && this.renderFilter(), this.includeFooterRecords && this.renderFooterRecords(this.collection.state),
  152. this.includeColumnManager && this.renderColumnManager();
  153. var pageSizeEl = null;
  154. if (this.includePageSize ? pageSizeEl = this.ui.selectPageSize : this.includeAtlasPageSize && (pageSizeEl = this.ui.showPage),
  155. pageSizeEl) {
  156. pageSizeEl.select2({
  157. data: _.sortBy(_.union([ 25, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500 ], [ this.collection.state.pageSize ])),
  158. tags: !0,
  159. dropdownCssClass: "number-input",
  160. multiple: !1
  161. });
  162. var val = this.collection.state.pageSize;
  163. this.value && this.value.pageLimit && (val = this.limit), pageSizeEl.val(val).trigger("change", {
  164. skipViewChange: !0
  165. });
  166. }
  167. },
  168. renderTable: function() {
  169. var that = this;
  170. this.grid = new Backgrid.Grid(this.gridOpts).on("backgrid:rendered", function() {
  171. that.trigger("backgrid:manual:rendered", this);
  172. }), this.showDefaultTableSorted ? (this.grid.render(), (this.collection.fullCollection.length > 1 || this.isApiSorting) && this.grid.sort(this.sortOpts.sortColumn, this.sortOpts.sortDirection),
  173. this.rTableList.show(this.grid)) : this.rTableList.show(this.grid);
  174. },
  175. onShow: function() {
  176. this.includeSizeAbleColumns && this.renderSizeAbleColumns(), this.includeOrderAbleColumns && this.renderOrderAbleColumns();
  177. },
  178. renderPagination: function() {
  179. var options = _.extend({
  180. collection: this.collection,
  181. controls: this.controlOpts
  182. }, this.paginatorOpts);
  183. this.rPagination ? this.rPagination.show(new Backgrid.Extension.Paginator(options)) : this.regions.rPagination && (this.$('div[data-id="r_pagination"]').show(new Backgrid.Extension.Paginator(options)),
  184. this.showHideGoToPage());
  185. },
  186. renderAtlasPagination: function(options) {
  187. var isFirstPage = 0 === this.offset, dataLength = this.collection.length, goToPage = this.ui.gotoPage.val();
  188. if (dataLength < this.limit ? this.ui.nextData.attr("disabled", !0) : this.ui.nextData.attr("disabled", !1),
  189. isFirstPage && (!dataLength || dataLength < this.limit) ? this.ui.paginationDiv.hide() : this.ui.paginationDiv.show(),
  190. isFirstPage ? (this.ui.previousData.attr("disabled", !0), this.pageFrom = 1, this.pageTo = this.limit) : this.ui.previousData.attr("disabled", !1),
  191. options && options.next ? (this.pageTo = this.offset + this.limit, this.pageFrom = this.offset + 1) : !isFirstPage && options && options.previous && (this.pageTo = this.pageTo - this.limit,
  192. this.pageFrom = this.pageTo - this.limit + 1), !this.isApiSorting || this.pageTo || this.pageFrom || (this.limit = this.count,
  193. this.pageTo = this.offset + this.limit, this.pageFrom = this.offset + 1), this.ui.pageRecordText.html("显示 <u>" + this.collection.length + " 条记录</u> 从 " + this.pageFrom + " - " + this.pageTo),
  194. this.activePage = Math.round(this.pageTo / this.limit), this.ui.activePage.attr("title", "第" + this.activePage+"页"),
  195. this.ui.activePage.text(this.activePage), this.ui.showPage.val(this.limit).trigger("change", {
  196. skipViewChange: !0
  197. }), !dataLength && this.offset >= this.limit && (options && options.next || goToPage) && options && !options.fromUrl) {
  198. var pageNumber = this.activePage;
  199. return goToPage ? (pageNumber = goToPage, this.offset = (this.activePage - 1) * this.limit) : this.ui.nextData.attr("disabled", !0),
  200. this.value && (this.value.pageOffset = this.offset, this.triggerUrl && this.triggerUrl()),
  201. void Utils.notifyInfo({
  202. html: !0,
  203. content: Messages.search.noRecordForPage + "<b>" + Utils.getNumberSuffix({
  204. number: pageNumber,
  205. sup: !0
  206. }) + "</b> 页"
  207. });
  208. }
  209. },
  210. showHidePager: function() {
  211. this.includePagination && (this.collection.state && this.collection.state.totalRecords > this.collection.state.pageSize ? this.$('div[data-id="r_pagination"]').show() : this.$('div[data-id="r_pagination"]').hide());
  212. },
  213. showHideGoToPage: function() {
  214. this.collection.state.pageSize > this.collection.fullCollection.length ? this.ui.paginationDiv.hide() : this.ui.paginationDiv.show();
  215. },
  216. renderFilter: function() {
  217. this.rFilter.show(new Backgrid.Extension.ServerSideFilter({
  218. collection: this.collection,
  219. name: [ "name" ],
  220. placeholder: "plcHldr.searchByResourcePath",
  221. wait: 150
  222. })), setTimeout(function() {
  223. that.$("table").colResizable({
  224. liveDrag: !0
  225. });
  226. }, 0);
  227. },
  228. renderFooterRecords: function(collectionState) {
  229. var collState = collectionState, totalRecords = collState.totalRecords || 0, pageStartIndex = totalRecords ? collState.currentPage * collState.pageSize : 0, pageEndIndex = pageStartIndex + this.collection.length;
  230. return this.$('[data-id="r_footerRecords"]').html("<h5>显示从 " + (totalRecords ? pageStartIndex + 1 : 0 === this.collection.length ? 0 : 1) + " 到 " + pageEndIndex + "</h5>"),
  231. this;
  232. },
  233. renderColumnManager: function() {
  234. if (this.columns) {
  235. var that = this, $el = this.columnOpts.el || this.$("[data-id='control']"), colManager = new Backgrid.Extension.ColumnManager(this.columns, this.columnOpts.opts), colVisibilityControl = new Backgrid.Extension.ColumnManagerVisibilityControl(_.extend({
  236. columnManager: colManager
  237. }, this.columnOpts.visibilityControlOpts));
  238. $el.jquery || ($el = $($el)), this.columnOpts.el ? $el.html(colVisibilityControl.render().el) : $el.append(colVisibilityControl.render().el),
  239. colManager.on("state-changed", function(state) {
  240. that.collection.trigger("state-changed", state);
  241. }), colManager.on("state-saved", function() {
  242. that.collection.trigger("state-changed");
  243. });
  244. }
  245. },
  246. renderSizeAbleColumns: function() {
  247. var sizeAbleCol = new Backgrid.Extension.SizeAbleColumns({
  248. collection: this.collection,
  249. columns: this.columns,
  250. grid: this.getGridObj()
  251. });
  252. this.$("thead").before(sizeAbleCol.render().el);
  253. var sizeHandler = new Backgrid.Extension.SizeAbleColumnsHandlers({
  254. sizeAbleColumns: sizeAbleCol,
  255. saveModelWidth: !0
  256. });
  257. this.$("thead").before(sizeHandler.render().el), this.columns.on("resize", function(columnModel, newWidth, oldWidth) {
  258. console.log("Resize event on column; name, model, new and old width: ", columnModel.get("name"), columnModel, newWidth, oldWidth);
  259. });
  260. },
  261. renderOrderAbleColumns: function() {
  262. var sizeAbleCol = new Backgrid.Extension.SizeAbleColumns({
  263. collection: this.collection,
  264. grid: this.getGridObj(),
  265. columns: this.columns
  266. });
  267. this.$("thead").before(sizeAbleCol.render().el);
  268. var orderHandler = new Backgrid.Extension.OrderableColumns({
  269. grid: this.getGridObj(),
  270. sizeAbleColumns: sizeAbleCol
  271. });
  272. this.$("thead").before(orderHandler.render().el);
  273. },
  274. onClose: function() {},
  275. getGridObj: function() {
  276. return this.rTableList.currentView ? this.rTableList.currentView : null;
  277. },
  278. onPageSizeChange: function(e, options) {
  279. if (!options || !options.skipViewChange) {
  280. var pagesize = $(e.currentTarget).val();
  281. if (0 == pagesize) return void this.ui.selectPageSize.data("select2").$container.addClass("has-error");
  282. this.ui.selectPageSize.data("select2").$container.removeClass("has-error"), this.collection.state.pageSize = parseInt(pagesize, 10),
  283. this.collection.state.currentPage = this.collection.state.firstPage, this.showHideGoToPage(),
  284. "client" == this.collection.mode ? this.collection.fullCollection.reset(this.collection.fullCollection.toJSON()) : this.collection.fetch({
  285. sort: !1,
  286. reset: !0,
  287. cache: !1
  288. });
  289. }
  290. },
  291. onClicknextData: function() {
  292. this.offset = this.offset + this.limit, _.extend(this.collection.queryParams, {
  293. offset: this.offset
  294. }), this.value && (this.value.pageOffset = this.offset, this.triggerUrl && this.triggerUrl()),
  295. this.fetchCollection && this.fetchCollection({
  296. next: !0
  297. });
  298. },
  299. onClickpreviousData: function() {
  300. this.offset = this.offset - this.limit, this.offset <= -1 && (this.offset = 0),
  301. _.extend(this.collection.queryParams, {
  302. offset: this.offset
  303. }), this.value && (this.value.pageOffset = this.offset, this.triggerUrl && this.triggerUrl()),
  304. this.fetchCollection && this.fetchCollection({
  305. previous: !0
  306. });
  307. },
  308. changePageLimit: function(e, obj) {
  309. if (!obj || obj && !obj.skipViewChange) {
  310. var limit = parseInt(this.ui.showPage.val());
  311. if (0 == limit) return void this.ui.showPage.data("select2").$container.addClass("has-error");
  312. this.ui.showPage.data("select2").$container.removeClass("has-error"), this.limit = limit,
  313. this.offset = 0, this.value && (this.value.pageLimit = this.limit, this.value.pageOffset = this.offset,
  314. this.triggerUrl && this.triggerUrl()), _.extend(this.collection.queryParams, {
  315. limit: this.limit,
  316. offset: this.offset
  317. }), this.fetchCollection();
  318. }
  319. },
  320. gotoPagebtn: function(e) {
  321. var that = this, goToPage = parseInt(this.ui.gotoPage.val());
  322. if (!_.isNaN(goToPage) && (0 == goToPage || this.collection.state.totalPages < goToPage)) return Utils.notifyInfo({
  323. content: Messages.search.noRecordForPage + "页 " + goToPage
  324. }), this.ui.gotoPage.val(""), void that.ui.gotoPagebtn.attr("disabled", !0);
  325. if (!(_.isNaN(goToPage) || goToPage <= -1)) {
  326. if ("client" == this.collection.mode) return this.collection.getPage(goToPage - 1, {
  327. reset: !0
  328. });
  329. this.offset = (goToPage - 1) * this.limit, this.offset <= -1 && (this.offset = 0),
  330. _.extend(this.collection.queryParams, {
  331. limit: this.limit,
  332. offset: this.offset
  333. }), this.offset == this.pageFrom - 1 ? Utils.notifyInfo({
  334. content: Messages.search.onSamePage
  335. }) : (this.value && (this.value.pageOffset = this.offset, this.triggerUrl && this.triggerUrl()),
  336. this.fetchCollection && this.fetchCollection({
  337. next: !0
  338. }));
  339. }
  340. }
  341. });
  342. return FSTableLayout;
  343. });