ui.data_grid.summary.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /**
  2. * DevExtreme (ui/data_grid/ui.data_grid.summary.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var _renderer = require("../../core/renderer");
  11. var _renderer2 = _interopRequireDefault(_renderer);
  12. var _common = require("../../core/utils/common");
  13. var _type = require("../../core/utils/type");
  14. var _iterator = require("../../core/utils/iterator");
  15. var _extend = require("../../core/utils/extend");
  16. var _data = require("../../core/utils/data");
  17. var _ui = require("../widget/ui.errors");
  18. var _ui2 = _interopRequireDefault(_ui);
  19. var _uiData_grid = require("./ui.data_grid.core");
  20. var _uiData_grid2 = _interopRequireDefault(_uiData_grid);
  21. var _message = require("../../localization/message");
  22. var _message2 = _interopRequireDefault(_message);
  23. var _uiData_grid3 = require("./ui.data_grid.data_source_adapter");
  24. var _uiData_grid4 = _interopRequireDefault(_uiData_grid3);
  25. var _uiGrid_core = require("../grid_core/ui.grid_core.columns_view");
  26. var _uiGrid_core2 = _interopRequireDefault(_uiGrid_core);
  27. var _aggregate_calculator = require("./aggregate_calculator");
  28. var _aggregate_calculator2 = _interopRequireDefault(_aggregate_calculator);
  29. var _query = require("../../data/query");
  30. var _query2 = _interopRequireDefault(_query);
  31. var _store_helper = require("../../data/store_helper");
  32. var _utils = require("../../data/utils");
  33. function _interopRequireDefault(obj) {
  34. return obj && obj.__esModule ? obj : {
  35. "default": obj
  36. }
  37. }
  38. var DATAGRID_TOTAL_FOOTER_CLASS = "dx-datagrid-total-footer";
  39. var DATAGRID_SUMMARY_ITEM_CLASS = "dx-datagrid-summary-item";
  40. var DATAGRID_TEXT_CONTENT_CLASS = "dx-datagrid-text-content";
  41. var DATAGRID_GROUP_FOOTER_CLASS = "dx-datagrid-group-footer";
  42. var DATAGRID_GROUP_TEXT_CONTENT_CLASS = "dx-datagrid-group-text-content";
  43. var DATAGRID_NOWRAP_CLASS = "dx-datagrid-nowrap";
  44. var DATAGRID_GROUP_FOOTER_ROW_TYPE = "groupFooter";
  45. var renderSummaryCell = function(cell, options) {
  46. var $cell = (0, _renderer2.default)(cell);
  47. var column = options.column;
  48. var summaryItems = options.summaryItems;
  49. var $summaryItems = [];
  50. if (!column.command && summaryItems) {
  51. for (var i = 0; i < summaryItems.length; i++) {
  52. var summaryItem = summaryItems[i];
  53. $summaryItems.push((0, _renderer2.default)("<div>").css("textAlign", summaryItem.alignment || column.alignment).addClass(DATAGRID_SUMMARY_ITEM_CLASS).addClass(DATAGRID_TEXT_CONTENT_CLASS).addClass(summaryItem.cssClass).toggleClass(DATAGRID_GROUP_TEXT_CONTENT_CLASS, "group" === options.rowType).text(_uiData_grid2.default.getSummaryText(summaryItem, options.summaryTexts)))
  54. }
  55. $cell.append($summaryItems)
  56. }
  57. };
  58. var getSummaryCellOptions = function(that, options) {
  59. var summaryTexts = that.option("summary.texts") || {};
  60. return {
  61. totalItem: options.row,
  62. summaryItems: options.row.summaryCells[options.columnIndex],
  63. summaryTexts: summaryTexts
  64. }
  65. };
  66. var getGroupAggregates = function(data) {
  67. return data.summary || data.aggregates || []
  68. };
  69. var recalculateWhileEditing = function(that) {
  70. return that.option("summary.recalculateWhileEditing")
  71. };
  72. exports.FooterView = _uiGrid_core2.default.ColumnsView.inherit(function() {
  73. return {
  74. _getRows: function() {
  75. return this._dataController.footerItems()
  76. },
  77. _getCellOptions: function(options) {
  78. return (0, _extend.extend)(this.callBase(options), getSummaryCellOptions(this, options))
  79. },
  80. _renderCellContent: function($cell, options) {
  81. renderSummaryCell($cell, options);
  82. this.callBase($cell, options)
  83. },
  84. _renderCore: function(change) {
  85. var needUpdateScrollLeft = false;
  86. var totalItem = this._dataController.footerItems()[0];
  87. if (!change || !change.columnIndices) {
  88. this.element().empty().addClass(DATAGRID_TOTAL_FOOTER_CLASS).toggleClass(DATAGRID_NOWRAP_CLASS, !this.option("wordWrapEnabled"));
  89. needUpdateScrollLeft = true
  90. }
  91. if (totalItem && totalItem.summaryCells && totalItem.summaryCells.length) {
  92. this._updateContent(this._renderTable({
  93. change: change
  94. }), change);
  95. needUpdateScrollLeft && this._updateScrollLeftPosition()
  96. }
  97. },
  98. _updateContent: function($newTable, change) {
  99. if (change && "update" === change.changeType && change.columnIndices) {
  100. var $row = this._getTableElement().find(".dx-row");
  101. var $newRow = $newTable.find(".dx-row");
  102. this._updateCells($row, $newRow, change.columnIndices[0])
  103. } else {
  104. return this.callBase.apply(this, arguments)
  105. }
  106. },
  107. _rowClick: function(e) {
  108. var item = this._dataController.footerItems()[e.rowIndex] || {};
  109. this.executeAction("onRowClick", (0, _extend.extend)({}, e, item))
  110. },
  111. _columnOptionChanged: function(e) {
  112. var optionNames = e.optionNames;
  113. if (e.changeTypes.grouping) {
  114. return
  115. }
  116. if (optionNames.width || optionNames.visibleWidth) {
  117. this.callBase(e)
  118. }
  119. },
  120. _handleDataChanged: function(e) {
  121. var changeType = e.changeType;
  122. if ("update" === e.changeType && e.repaintChangesOnly) {
  123. if (!e.totalColumnIndices) {
  124. this.render()
  125. } else {
  126. if (e.totalColumnIndices.length) {
  127. this.render(null, {
  128. changeType: "update",
  129. columnIndices: [e.totalColumnIndices]
  130. })
  131. }
  132. }
  133. } else {
  134. if ("refresh" === changeType || "append" === changeType || "prepend" === changeType) {
  135. this.render()
  136. }
  137. }
  138. },
  139. getHeight: function() {
  140. return this.getElementHeight()
  141. },
  142. isVisible: function() {
  143. return !!this._dataController.footerItems().length
  144. }
  145. }
  146. }());
  147. var SummaryDataSourceAdapterExtender = function() {
  148. function forEachGroup(groups, groupCount, callback, path) {
  149. path = path || [];
  150. for (var i = 0; i < groups.length; i++) {
  151. path.push(groups[i].key);
  152. if (1 === groupCount) {
  153. callback(path, groups[i].items)
  154. } else {
  155. forEachGroup(groups[i].items, groupCount - 1, callback, path)
  156. }
  157. path.pop()
  158. }
  159. }
  160. return {
  161. init: function() {
  162. this.callBase.apply(this, arguments);
  163. this._totalAggregates = [];
  164. this._summaryGetter = _common.noop
  165. },
  166. summaryGetter: function(_summaryGetter) {
  167. if (!arguments.length) {
  168. return this._summaryGetter
  169. }
  170. if ((0, _type.isFunction)(_summaryGetter)) {
  171. this._summaryGetter = _summaryGetter
  172. }
  173. },
  174. summary: function(_summary) {
  175. if (!arguments.length) {
  176. return this._summaryGetter()
  177. }
  178. this._summaryGetter = function() {
  179. return _summary
  180. }
  181. },
  182. totalAggregates: function() {
  183. return this._totalAggregates
  184. },
  185. isLastLevelGroupItemsPagingLocal: function() {
  186. var summary = this.summary();
  187. var sortByGroupsInfo = summary && summary.sortByGroups();
  188. return sortByGroupsInfo && sortByGroupsInfo.length
  189. },
  190. sortLastLevelGroupItems: function(items, groups, paths) {
  191. var groupedItems = (0, _store_helper.multiLevelGroup)((0, _query2.default)(items), groups).toArray();
  192. var result = [];
  193. paths.forEach(function(path) {
  194. forEachGroup(groupedItems, groups.length, function(itemsPath, items) {
  195. if (path.toString() === itemsPath.toString()) {
  196. result = result.concat(items)
  197. }
  198. })
  199. });
  200. return result
  201. }
  202. }
  203. }();
  204. var SummaryDataSourceAdapterClientExtender = function() {
  205. var applyAddedData = function applyAddedData(data, insertedData, groupLevel) {
  206. if (groupLevel) {
  207. return applyAddedData(data, insertedData.map(function(item) {
  208. return {
  209. items: [item]
  210. }
  211. }, groupLevel - 1))
  212. }
  213. return data.concat(insertedData)
  214. };
  215. var applyRemovedData = function applyRemovedData(data, removedData, groupLevel) {
  216. if (groupLevel) {
  217. return data.map(function(data) {
  218. var updatedData = {};
  219. var updatedItems = applyRemovedData(data.items || [], removedData, groupLevel - 1);
  220. Object.defineProperty(updatedData, "aggregates", {
  221. get: function() {
  222. return data.aggregates
  223. },
  224. set: function(value) {
  225. data.aggregates = value
  226. }
  227. });
  228. return (0, _extend.extend)(updatedData, data, {
  229. items: updatedItems
  230. })
  231. })
  232. }
  233. return data.filter(function(data) {
  234. return removedData.indexOf(data) < 0
  235. })
  236. };
  237. var calculateAggregates = function(that, summary, data, groupLevel) {
  238. var calculator;
  239. if (recalculateWhileEditing(that)) {
  240. var editingController = that.getController("editing");
  241. if (editingController) {
  242. var insertedData = editingController.getInsertedData();
  243. if (insertedData.length) {
  244. data = applyAddedData(data, insertedData, groupLevel)
  245. }
  246. var removedData = editingController.getRemovedData();
  247. if (removedData.length) {
  248. data = applyRemovedData(data, removedData, groupLevel)
  249. }
  250. }
  251. }
  252. if (summary) {
  253. calculator = new _aggregate_calculator2.default({
  254. totalAggregates: summary.totalAggregates,
  255. groupAggregates: summary.groupAggregates,
  256. data: data,
  257. groupLevel: groupLevel
  258. });
  259. calculator.calculate()
  260. }
  261. return calculator ? calculator.totalAggregates() : []
  262. };
  263. var sortGroupsBySummaryCore = function sortGroupsBySummaryCore(items, groups, sortByGroups) {
  264. if (!items || !groups.length) {
  265. return items
  266. }
  267. var group = groups[0];
  268. var sorts = sortByGroups[0];
  269. var query;
  270. if (group && sorts && sorts.length) {
  271. query = (0, _query2.default)(items);
  272. (0, _iterator.each)(sorts, function(index) {
  273. if (0 === index) {
  274. query = query.sortBy(this.selector, this.desc)
  275. } else {
  276. query = query.thenBy(this.selector, this.desc)
  277. }
  278. });
  279. query.enumerate().done(function(sortedItems) {
  280. items = sortedItems
  281. })
  282. }
  283. groups = groups.slice(1);
  284. sortByGroups = sortByGroups.slice(1);
  285. if (groups.length && sortByGroups.length) {
  286. (0, _iterator.each)(items, function() {
  287. this.items = sortGroupsBySummaryCore(this.items, groups, sortByGroups)
  288. })
  289. }
  290. return items
  291. };
  292. var sortGroupsBySummary = function(data, group, summary) {
  293. var sortByGroups = summary && summary.sortByGroups && summary.sortByGroups();
  294. if (sortByGroups && sortByGroups.length) {
  295. return sortGroupsBySummaryCore(data, group, sortByGroups)
  296. }
  297. return data
  298. };
  299. return {
  300. _customizeRemoteOperations: function(options) {
  301. var summary = this.summary();
  302. if (summary) {
  303. if (options.remoteOperations.summary) {
  304. if (!options.isCustomLoading || options.storeLoadOptions.isLoadingAll) {
  305. if (options.storeLoadOptions.group) {
  306. if (options.remoteOperations.grouping) {
  307. options.storeLoadOptions.groupSummary = summary.groupAggregates
  308. } else {
  309. if (summary.groupAggregates.length) {
  310. options.remoteOperations.paging = false
  311. }
  312. }
  313. }
  314. options.storeLoadOptions.totalSummary = summary.totalAggregates
  315. }
  316. } else {
  317. if (summary.totalAggregates.length || summary.groupAggregates.length && options.storeLoadOptions.group) {
  318. options.remoteOperations.paging = false
  319. }
  320. }
  321. }
  322. this.callBase.apply(this, arguments);
  323. var cachedExtra = options.cachedPagesData.extra;
  324. if (cachedExtra && cachedExtra.summary && !options.isCustomLoading) {
  325. options.storeLoadOptions.totalSummary = void 0
  326. }
  327. },
  328. _handleDataLoadedCore: function(options) {
  329. var that = this;
  330. var groups = (0, _utils.normalizeSortingInfo)(options.storeLoadOptions.group || options.loadOptions.group || []);
  331. var remoteOperations = options.remoteOperations || {};
  332. var summary = that.summaryGetter()(remoteOperations);
  333. var totalAggregates;
  334. if (!options.isCustomLoading || options.storeLoadOptions.isLoadingAll) {
  335. if (remoteOperations.summary) {
  336. if (!remoteOperations.paging && groups.length && summary) {
  337. if (!remoteOperations.grouping) {
  338. calculateAggregates(that, {
  339. groupAggregates: summary.groupAggregates
  340. }, options.data, groups.length)
  341. }
  342. options.data = sortGroupsBySummary(options.data, groups, summary)
  343. }
  344. } else {
  345. if (!remoteOperations.paging) {
  346. totalAggregates = calculateAggregates(that, summary, options.data, groups.length);
  347. options.data = sortGroupsBySummary(options.data, groups, summary);
  348. options.extra = (0, _type.isPlainObject)(options.extra) ? options.extra : {};
  349. options.extra.summary = totalAggregates
  350. }
  351. }
  352. }
  353. if (!options.isCustomLoading) {
  354. that._totalAggregates = options.extra && options.extra.summary || that._totalAggregates
  355. }
  356. that.callBase(options)
  357. }
  358. }
  359. }();
  360. _uiData_grid4.default.extend(SummaryDataSourceAdapterExtender);
  361. _uiData_grid4.default.extend(SummaryDataSourceAdapterClientExtender);
  362. exports.renderSummaryCell = renderSummaryCell;
  363. _uiData_grid2.default.registerModule("summary", {
  364. defaultOptions: function() {
  365. return {
  366. summary: {
  367. groupItems: void 0,
  368. totalItems: void 0,
  369. calculateCustomSummary: void 0,
  370. skipEmptyValues: true,
  371. recalculateWhileEditing: false,
  372. texts: {
  373. sum: _message2.default.getFormatter("dxDataGrid-summarySum"),
  374. sumOtherColumn: _message2.default.getFormatter("dxDataGrid-summarySumOtherColumn"),
  375. min: _message2.default.getFormatter("dxDataGrid-summaryMin"),
  376. minOtherColumn: _message2.default.getFormatter("dxDataGrid-summaryMinOtherColumn"),
  377. max: _message2.default.getFormatter("dxDataGrid-summaryMax"),
  378. maxOtherColumn: _message2.default.getFormatter("dxDataGrid-summaryMaxOtherColumn"),
  379. avg: _message2.default.getFormatter("dxDataGrid-summaryAvg"),
  380. avgOtherColumn: _message2.default.getFormatter("dxDataGrid-summaryAvgOtherColumn"),
  381. count: _message2.default.getFormatter("dxDataGrid-summaryCount")
  382. }
  383. },
  384. sortByGroupSummaryInfo: void 0
  385. }
  386. },
  387. views: {
  388. footerView: exports.FooterView
  389. },
  390. extenders: {
  391. controllers: {
  392. data: function() {
  393. return {
  394. _isDataColumn: function(column) {
  395. return column && (!(0, _type.isDefined)(column.groupIndex) || column.showWhenGrouped)
  396. },
  397. _isGroupFooterVisible: function() {
  398. var groupItems = this.option("summary.groupItems") || [];
  399. for (var i = 0; i < groupItems.length; i++) {
  400. var groupItem = groupItems[i];
  401. var column = this._columnsController.columnOption(groupItem.showInColumn || groupItem.column);
  402. if (groupItem.showInGroupFooter && this._isDataColumn(column)) {
  403. return true
  404. }
  405. }
  406. return false
  407. },
  408. _processGroupItems: function(items, groupCount, options) {
  409. var data = options && options.data;
  410. var result = this.callBase.apply(this, arguments);
  411. if (options) {
  412. if (void 0 === options.isGroupFooterVisible) {
  413. options.isGroupFooterVisible = this._isGroupFooterVisible()
  414. }
  415. if (data && data.items && options.isGroupFooterVisible && (options.collectContinuationItems || !data.isContinuationOnNextPage)) {
  416. result.push({
  417. rowType: DATAGRID_GROUP_FOOTER_ROW_TYPE,
  418. key: options.path.slice(),
  419. data: data,
  420. groupIndex: options.path.length - 1,
  421. values: []
  422. })
  423. }
  424. }
  425. return result
  426. },
  427. _processGroupItem: function(groupItem, options) {
  428. var that = this;
  429. if (!options.summaryGroupItems) {
  430. options.summaryGroupItems = that.option("summary.groupItems") || []
  431. }
  432. if ("group" === groupItem.rowType) {
  433. var groupColumnIndex = -1;
  434. var afterGroupColumnIndex = -1;
  435. (0, _iterator.each)(options.visibleColumns, function(visibleIndex) {
  436. var prevColumn = options.visibleColumns[visibleIndex - 1];
  437. if (groupItem.groupIndex === this.groupIndex) {
  438. groupColumnIndex = this.index
  439. }
  440. if (visibleIndex > 0 && "expand" === prevColumn.command && "expand" !== this.command) {
  441. afterGroupColumnIndex = this.index
  442. }
  443. });
  444. groupItem.summaryCells = this._calculateSummaryCells(options.summaryGroupItems, getGroupAggregates(groupItem.data), options.visibleColumns, function(summaryItem, column) {
  445. if (summaryItem.showInGroupFooter) {
  446. return -1
  447. }
  448. if (summaryItem.alignByColumn && column && !(0, _type.isDefined)(column.groupIndex) && column.index !== afterGroupColumnIndex) {
  449. return column.index
  450. } else {
  451. return groupColumnIndex
  452. }
  453. })
  454. }
  455. if (groupItem.rowType === DATAGRID_GROUP_FOOTER_ROW_TYPE) {
  456. groupItem.summaryCells = this._calculateSummaryCells(options.summaryGroupItems, getGroupAggregates(groupItem.data), options.visibleColumns, function(summaryItem, column) {
  457. return summaryItem.showInGroupFooter && that._isDataColumn(column) ? column.index : -1
  458. })
  459. }
  460. return groupItem
  461. },
  462. _calculateSummaryCells: function(summaryItems, aggregates, visibleColumns, calculateTargetColumnIndex) {
  463. var that = this;
  464. var summaryCells = [];
  465. var summaryCellsByColumns = {};
  466. (0, _iterator.each)(summaryItems, function(summaryIndex, summaryItem) {
  467. var column = that._columnsController.columnOption(summaryItem.column);
  468. var showInColumn = summaryItem.showInColumn && that._columnsController.columnOption(summaryItem.showInColumn) || column;
  469. var columnIndex = calculateTargetColumnIndex(summaryItem, showInColumn);
  470. if (columnIndex >= 0) {
  471. if (!summaryCellsByColumns[columnIndex]) {
  472. summaryCellsByColumns[columnIndex] = []
  473. }
  474. var aggregate = aggregates[summaryIndex];
  475. if (aggregate === aggregate) {
  476. var valueFormat;
  477. if ((0, _type.isDefined)(summaryItem.valueFormat)) {
  478. valueFormat = summaryItem.valueFormat
  479. } else {
  480. if ("count" !== summaryItem.summaryType) {
  481. valueFormat = _uiData_grid2.default.getFormatByDataType(column && column.dataType)
  482. }
  483. }
  484. summaryCellsByColumns[columnIndex].push((0, _extend.extend)({}, summaryItem, {
  485. value: (0, _type.isString)(aggregate) && column && column.deserializeValue ? column.deserializeValue(aggregate) : aggregate,
  486. valueFormat: valueFormat,
  487. columnCaption: column && column.index !== columnIndex ? column.caption : void 0
  488. }))
  489. }
  490. }
  491. });
  492. if (!(0, _type.isEmptyObject)(summaryCellsByColumns)) {
  493. (0, _iterator.each)(visibleColumns, function() {
  494. summaryCells.push(summaryCellsByColumns[this.index] || [])
  495. })
  496. }
  497. return summaryCells
  498. },
  499. _getSummaryCells: function(summaryTotalItems, totalAggregates) {
  500. var that = this;
  501. var columnsController = that._columnsController;
  502. return that._calculateSummaryCells(summaryTotalItems, totalAggregates, columnsController.getVisibleColumns(), function(summaryItem, column) {
  503. return that._isDataColumn(column) ? column.index : -1
  504. })
  505. },
  506. _updateItemsCore: function(change) {
  507. var that = this;
  508. var dataSource = that._dataSource;
  509. var footerItems = that._footerItems;
  510. var oldSummaryCells = footerItems && footerItems[0] && footerItems[0].summaryCells;
  511. var summaryTotalItems = that.option("summary.totalItems");
  512. that._footerItems = [];
  513. if (dataSource && summaryTotalItems && summaryTotalItems.length) {
  514. var totalAggregates = dataSource.totalAggregates();
  515. var summaryCells = that._getSummaryCells(summaryTotalItems, totalAggregates);
  516. if (change && change.repaintChangesOnly && oldSummaryCells) {
  517. change.totalColumnIndices = summaryCells.map(function(summaryCell, index) {
  518. if (JSON.stringify(summaryCell) !== JSON.stringify(oldSummaryCells[index])) {
  519. return index
  520. }
  521. return -1
  522. }).filter(function(index) {
  523. return index >= 0
  524. })
  525. }
  526. if (summaryCells.length) {
  527. that._footerItems.push({
  528. rowType: "totalFooter",
  529. summaryCells: summaryCells
  530. })
  531. }
  532. }
  533. that.callBase(change)
  534. },
  535. _prepareUnsavedDataSelector: function(selector) {
  536. var that = this;
  537. if (recalculateWhileEditing(that)) {
  538. var editingController = that.getController("editing");
  539. if (editingController) {
  540. return function(data) {
  541. data = editingController.getUpdatedData(data);
  542. return selector(data)
  543. }
  544. }
  545. }
  546. return selector
  547. },
  548. _prepareAggregateSelector: function(selector, aggregator) {
  549. selector = this._prepareUnsavedDataSelector(selector);
  550. if ("avg" === aggregator || "sum" === aggregator) {
  551. return function(data) {
  552. var value = selector(data);
  553. return (0, _type.isDefined)(value) ? Number(value) : value
  554. }
  555. }
  556. return selector
  557. },
  558. _getAggregates: function(summaryItems, remoteOperations) {
  559. var that = this;
  560. var columnsController = that.getController("columns");
  561. var calculateCustomSummary = that.option("summary.calculateCustomSummary");
  562. var commonSkipEmptyValues = that.option("summary.skipEmptyValues");
  563. return (0, _iterator.map)(summaryItems || [], function(summaryItem) {
  564. var column = columnsController.columnOption(summaryItem.column);
  565. var calculateCellValue = column && column.calculateCellValue ? column.calculateCellValue.bind(column) : (0, _data.compileGetter)(column ? column.dataField : summaryItem.column);
  566. var aggregator = summaryItem.summaryType || "count";
  567. var selector = summaryItem.column;
  568. var skipEmptyValues = (0, _type.isDefined)(summaryItem.skipEmptyValues) ? summaryItem.skipEmptyValues : commonSkipEmptyValues;
  569. if (remoteOperations) {
  570. return {
  571. selector: summaryItem.column,
  572. summaryType: aggregator
  573. }
  574. } else {
  575. selector = that._prepareAggregateSelector(calculateCellValue, aggregator);
  576. if ("custom" === aggregator) {
  577. if (!calculateCustomSummary) {
  578. _ui2.default.log("E1026");
  579. calculateCustomSummary = function() {}
  580. }
  581. var options = {
  582. component: that.component,
  583. name: summaryItem.name
  584. };
  585. calculateCustomSummary(options);
  586. options.summaryProcess = "calculate";
  587. aggregator = {
  588. seed: function(groupIndex) {
  589. options.summaryProcess = "start";
  590. options.totalValue = void 0;
  591. options.groupIndex = groupIndex;
  592. delete options.value;
  593. calculateCustomSummary(options);
  594. return options.totalValue
  595. },
  596. step: function(totalValue, value) {
  597. options.summaryProcess = "calculate";
  598. options.totalValue = totalValue;
  599. options.value = value;
  600. calculateCustomSummary(options);
  601. return options.totalValue
  602. },
  603. finalize: function(totalValue) {
  604. options.summaryProcess = "finalize";
  605. options.totalValue = totalValue;
  606. delete options.value;
  607. calculateCustomSummary(options);
  608. return options.totalValue
  609. }
  610. }
  611. }
  612. return {
  613. selector: selector,
  614. aggregator: aggregator,
  615. skipEmptyValues: skipEmptyValues
  616. }
  617. }
  618. })
  619. },
  620. _addSortInfo: function(sortByGroups, groupColumn, selector, sortOrder) {
  621. if (groupColumn) {
  622. var groupIndex = groupColumn.groupIndex;
  623. sortOrder = sortOrder || groupColumn.sortOrder;
  624. if ((0, _type.isDefined)(groupIndex)) {
  625. sortByGroups[groupIndex] = sortByGroups[groupIndex] || [];
  626. sortByGroups[groupIndex].push({
  627. selector: selector,
  628. desc: "desc" === sortOrder
  629. })
  630. }
  631. }
  632. },
  633. _findSummaryItem: function(summaryItems, name) {
  634. var summaryItemIndex = -1;
  635. var getFullName = function(summaryItem) {
  636. var summaryType = summaryItem.summaryType;
  637. var column = summaryItem.column;
  638. return summaryType && column && summaryType + "_" + column
  639. };
  640. if ((0, _type.isDefined)(name)) {
  641. (0, _iterator.each)(summaryItems || [], function(index) {
  642. if (this.name === name || index === name || this.summaryType === name || this.column === name || getFullName(this) === name) {
  643. summaryItemIndex = index;
  644. return false
  645. }
  646. })
  647. }
  648. return summaryItemIndex
  649. },
  650. _getSummarySortByGroups: function(sortByGroupSummaryInfo, groupSummaryItems) {
  651. var that = this;
  652. var columnsController = that._columnsController;
  653. var groupColumns = columnsController.getGroupColumns();
  654. var sortByGroups = [];
  655. if (!groupSummaryItems || !groupSummaryItems.length) {
  656. return
  657. }(0, _iterator.each)(sortByGroupSummaryInfo || [], function() {
  658. var sortOrder = this.sortOrder;
  659. var groupColumn = this.groupColumn;
  660. var summaryItemIndex = that._findSummaryItem(groupSummaryItems, this.summaryItem);
  661. if (summaryItemIndex < 0) {
  662. return
  663. }
  664. var selector = function(data) {
  665. return getGroupAggregates(data)[summaryItemIndex]
  666. };
  667. if ((0, _type.isDefined)(groupColumn)) {
  668. groupColumn = columnsController.columnOption(groupColumn);
  669. that._addSortInfo(sortByGroups, groupColumn, selector, sortOrder)
  670. } else {
  671. (0, _iterator.each)(groupColumns, function(groupIndex, groupColumn) {
  672. that._addSortInfo(sortByGroups, groupColumn, selector, sortOrder)
  673. })
  674. }
  675. });
  676. return sortByGroups
  677. },
  678. _createDataSourceAdapterCore: function(dataSource, remoteOperations) {
  679. var that = this;
  680. var dataSourceAdapter = this.callBase(dataSource, remoteOperations);
  681. dataSourceAdapter.summaryGetter(function(currentRemoteOperations) {
  682. return that._getSummaryOptions(currentRemoteOperations || remoteOperations)
  683. });
  684. return dataSourceAdapter
  685. },
  686. _getSummaryOptions: function(remoteOperations) {
  687. var that = this;
  688. var groupSummaryItems = that.option("summary.groupItems");
  689. var totalSummaryItems = that.option("summary.totalItems");
  690. var sortByGroupSummaryInfo = that.option("sortByGroupSummaryInfo");
  691. var groupAggregates = that._getAggregates(groupSummaryItems, remoteOperations && remoteOperations.grouping && remoteOperations.summary);
  692. var totalAggregates = that._getAggregates(totalSummaryItems, remoteOperations && remoteOperations.summary);
  693. var sortByGroups = function() {
  694. return that._getSummarySortByGroups(sortByGroupSummaryInfo, groupSummaryItems)
  695. };
  696. if (groupAggregates.length || totalAggregates.length) {
  697. return {
  698. groupAggregates: groupAggregates,
  699. totalAggregates: totalAggregates,
  700. sortByGroups: sortByGroups
  701. }
  702. }
  703. },
  704. publicMethods: function() {
  705. var methods = this.callBase();
  706. methods.push("getTotalSummaryValue");
  707. return methods
  708. },
  709. getTotalSummaryValue: function(summaryItemName) {
  710. var summaryItemIndex = this._findSummaryItem(this.option("summary.totalItems"), summaryItemName);
  711. var aggregates = this._dataSource.totalAggregates();
  712. if (aggregates.length && summaryItemIndex > -1) {
  713. return aggregates[summaryItemIndex]
  714. }
  715. },
  716. optionChanged: function(args) {
  717. if ("summary" === args.name || "sortByGroupSummaryInfo" === args.name) {
  718. args.name = "dataSource"
  719. }
  720. this.callBase(args)
  721. },
  722. init: function() {
  723. this._footerItems = [];
  724. this.callBase()
  725. },
  726. footerItems: function() {
  727. return this._footerItems
  728. }
  729. }
  730. }(),
  731. editing: function() {
  732. return {
  733. _refreshSummary: function() {
  734. if (recalculateWhileEditing(this)) {
  735. this._dataController.refresh({
  736. load: true,
  737. changesOnly: true
  738. })
  739. }
  740. },
  741. _addEditData: function(params) {
  742. var result = this.callBase.apply(this, arguments);
  743. if (params.type) {
  744. this._refreshSummary()
  745. }
  746. return result
  747. },
  748. _removeEditDataItem: function() {
  749. var result = this.callBase.apply(this, arguments);
  750. this._refreshSummary();
  751. return result
  752. },
  753. cancelEditData: function() {
  754. var result = this.callBase.apply(this, arguments);
  755. this._refreshSummary();
  756. return result
  757. }
  758. }
  759. }()
  760. },
  761. views: {
  762. rowsView: function() {
  763. return {
  764. _createRow: function(row) {
  765. var $row = this.callBase(row);
  766. row && $row.addClass(row.rowType === DATAGRID_GROUP_FOOTER_ROW_TYPE ? DATAGRID_GROUP_FOOTER_CLASS : "");
  767. return $row
  768. },
  769. _renderCells: function($row, options) {
  770. this.callBase.apply(this, arguments);
  771. if ("group" === options.row.rowType && options.row.summaryCells && options.row.summaryCells.length) {
  772. this._renderGroupSummaryCells($row, options)
  773. }
  774. },
  775. _hasAlignByColumnSummaryItems: function(columnIndex, options) {
  776. return !(0, _type.isDefined)(options.columns[columnIndex].groupIndex) && options.row.summaryCells[columnIndex].length
  777. },
  778. _getAlignByColumnCellCount: function(groupCellColSpan, options) {
  779. var alignByColumnCellCount = 0;
  780. for (var i = 1; i < groupCellColSpan; i++) {
  781. var columnIndex = options.row.summaryCells.length - i;
  782. alignByColumnCellCount = this._hasAlignByColumnSummaryItems(columnIndex, options) ? i : alignByColumnCellCount
  783. }
  784. return alignByColumnCellCount
  785. },
  786. _renderGroupSummaryCells: function($row, options) {
  787. var $groupCell = $row.children().last();
  788. var groupCellColSpan = Number($groupCell.attr("colSpan")) || 1;
  789. var alignByColumnCellCount = this._getAlignByColumnCellCount(groupCellColSpan, options);
  790. this._renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount)
  791. },
  792. _renderGroupSummaryCellsCore: function($groupCell, options, groupCellColSpan, alignByColumnCellCount) {
  793. if (alignByColumnCellCount > 0) {
  794. $groupCell.attr("colSpan", groupCellColSpan - alignByColumnCellCount);
  795. for (var i = 0; i < alignByColumnCellCount; i++) {
  796. var columnIndex = options.columns.length - alignByColumnCellCount + i;
  797. this._renderCell($groupCell.parent(), (0, _extend.extend)({
  798. column: options.columns[columnIndex],
  799. columnIndex: this._getSummaryCellIndex(columnIndex, options.columns)
  800. }, options))
  801. }
  802. }
  803. },
  804. _getSummaryCellIndex: function(columnIndex) {
  805. return columnIndex
  806. },
  807. _getCellTemplate: function(options) {
  808. if (!options.column.command && !(0, _type.isDefined)(options.column.groupIndex) && options.summaryItems && options.summaryItems.length) {
  809. return renderSummaryCell
  810. } else {
  811. return this.callBase(options)
  812. }
  813. },
  814. _getCellOptions: function(options) {
  815. var that = this;
  816. var parameters = that.callBase(options);
  817. if (options.row.summaryCells) {
  818. return (0, _extend.extend)(parameters, getSummaryCellOptions(that, options))
  819. } else {
  820. return parameters
  821. }
  822. }
  823. }
  824. }()
  825. }
  826. }
  827. });