|
|
@@ -1,152 +1,5 @@
|
|
|
-/**
|
|
|
- * This feature is used to place a summary row at the bottom of the grid. If using a grouping,
|
|
|
- * see {@link Ext.grid.feature.GroupingSummary}. There are 2 aspects to calculating the summaries,
|
|
|
- * calculation and rendering.
|
|
|
- *
|
|
|
- * ## Calculation
|
|
|
- * The summary value needs to be calculated for each column in the grid. This is controlled
|
|
|
- * by the summaryType option specified on the column. There are several built in summary types,
|
|
|
- * which can be specified as a string on the column configuration. These call underlying methods
|
|
|
- * on the store:
|
|
|
- *
|
|
|
- * - {@link Ext.data.Store#count count}
|
|
|
- * - {@link Ext.data.Store#sum sum}
|
|
|
- * - {@link Ext.data.Store#min min}
|
|
|
- * - {@link Ext.data.Store#max max}
|
|
|
- * - {@link Ext.data.Store#average average}
|
|
|
- *
|
|
|
- * Alternatively, the summaryType can be a function definition. If this is the case,
|
|
|
- * the function is called with an array of records to calculate the summary value.
|
|
|
- *
|
|
|
- * ## Rendering
|
|
|
- * Similar to a column, the summary also supports a summaryRenderer function. This
|
|
|
- * summaryRenderer is called before displaying a value. The function is optional, if
|
|
|
- * not specified the default calculated value is shown. The summaryRenderer is called with:
|
|
|
- *
|
|
|
- * - value {Object} - The calculated value.
|
|
|
- * - summaryData {Object} - Contains all raw summary values for the row.
|
|
|
- * - field {String} - The name of the field we are calculating
|
|
|
- * - metaData {Object} - A collection of metadata about the current cell; can be used or modified by the renderer.
|
|
|
- *
|
|
|
- * ## Example Usage
|
|
|
- *
|
|
|
- * @example
|
|
|
- * Ext.define('TestResult', {
|
|
|
- * extend: 'Ext.data.Model',
|
|
|
- * fields: ['student', {
|
|
|
- * name: 'mark',
|
|
|
- * type: 'int'
|
|
|
- * }]
|
|
|
- * });
|
|
|
- *
|
|
|
- * Ext.create('Ext.grid.Panel', {
|
|
|
- * width: 400,
|
|
|
- * height: 200,
|
|
|
- * title: 'Summary Test',
|
|
|
- * style: 'padding: 20px',
|
|
|
- * renderTo: document.body,
|
|
|
- * features: [{
|
|
|
- * ftype: 'summary'
|
|
|
- * }],
|
|
|
- * store: {
|
|
|
- * model: 'TestResult',
|
|
|
- * data: [{
|
|
|
- * student: 'Student 1',
|
|
|
- * mark: 84
|
|
|
- * },{
|
|
|
- * student: 'Student 2',
|
|
|
- * mark: 72
|
|
|
- * },{
|
|
|
- * student: 'Student 3',
|
|
|
- * mark: 96
|
|
|
- * },{
|
|
|
- * student: 'Student 4',
|
|
|
- * mark: 68
|
|
|
- * }]
|
|
|
- * },
|
|
|
- * columns: [{
|
|
|
- * dataIndex: 'student',
|
|
|
- * text: 'Name',
|
|
|
- * summaryType: 'count',
|
|
|
- * summaryRenderer: function(value, summaryData, dataIndex) {
|
|
|
- * return Ext.String.format('{0} student{1}', value, value !== 1 ? 's' : '');
|
|
|
- * }
|
|
|
- * }, {
|
|
|
- * dataIndex: 'mark',
|
|
|
- * text: 'Mark',
|
|
|
- * summaryType: 'average'
|
|
|
- * }]
|
|
|
- * });
|
|
|
- */
|
|
|
-Ext.define('Ext.grid.feature.Summary', {
|
|
|
-
|
|
|
- /* Begin Definitions */
|
|
|
-
|
|
|
- extend: 'Ext.grid.feature.AbstractSummary',
|
|
|
-
|
|
|
- alias: 'feature.summary',
|
|
|
-
|
|
|
- /**
|
|
|
- * @cfg {String} dock
|
|
|
- * Configure `'top'` or `'bottom'` top create a fixed summary row either above or below the scrollable table.
|
|
|
- *
|
|
|
- */
|
|
|
- dock: undefined,
|
|
|
-
|
|
|
- summaryItemCls: Ext.baseCSSPrefix + 'grid-row-summary-item',
|
|
|
- dockedSummaryCls: Ext.baseCSSPrefix + 'docked-summary',
|
|
|
-
|
|
|
- summaryRowCls: Ext.baseCSSPrefix + 'grid-row-summary ' + Ext.baseCSSPrefix + 'grid-row-total',
|
|
|
- summaryRowSelector: '.' + Ext.baseCSSPrefix + 'grid-row-summary.' + Ext.baseCSSPrefix + 'grid-row-total',
|
|
|
-
|
|
|
- panelBodyCls: Ext.baseCSSPrefix + 'summary-',
|
|
|
-
|
|
|
- // turn off feature events.
|
|
|
- hasFeatureEvent: false,
|
|
|
-
|
|
|
- fullSummaryTpl: {
|
|
|
- fn: function (out, values, parent) {
|
|
|
- var me = this.summaryFeature,
|
|
|
- record = me.summaryRecord,
|
|
|
- view = values.view,
|
|
|
- bufferedRenderer = view.bufferedRenderer;
|
|
|
-
|
|
|
- this.nextTpl.applyOut(values, out, parent);
|
|
|
-
|
|
|
- if (!me.disabled && me.showSummaryRow && !view.addingRows && view.store.isLast(values.record)) {
|
|
|
- if (bufferedRenderer && !me.dock) {
|
|
|
- bufferedRenderer.variableRowHeight = true;
|
|
|
- }
|
|
|
- me.outputSummaryRecord((record && record.isModel) ? record : me.createSummaryRecord(view), values, out, parent);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- priority: 300,
|
|
|
-
|
|
|
- beginRowSync: function (rowSync) {
|
|
|
- rowSync.add('fullSummary', this.summaryFeature.summaryRowSelector);
|
|
|
- },
|
|
|
-
|
|
|
- syncContent: function (destRow, sourceRow, columnsToUpdate) {
|
|
|
- destRow = Ext.fly(destRow, 'syncDest');
|
|
|
- sourceRow = Ext.fly(sourceRow, 'sycSrc');
|
|
|
- var summaryFeature = this.summaryFeature,
|
|
|
- selector = summaryFeature.summaryRowSelector,
|
|
|
- destSummaryRow = destRow.down(selector, true),
|
|
|
- sourceSummaryRow = sourceRow.down(selector, true);
|
|
|
-
|
|
|
- // Sync just the updated columns in the summary row.
|
|
|
- if (destSummaryRow && sourceSummaryRow) {
|
|
|
-
|
|
|
- // If we were passed a column set, only update those, otherwise do the entire row
|
|
|
- if (columnsToUpdate) {
|
|
|
- this.summaryFeature.view.updateColumns(destSummaryRow, sourceSummaryRow, columnsToUpdate);
|
|
|
- } else {
|
|
|
- Ext.fly(destSummaryRow).syncContent(sourceSummaryRow);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
+Ext.define('Ext.overrides.grid.feature.Summary', {
|
|
|
+ override: 'Ext.grid.feature.Summary',
|
|
|
|
|
|
// override
|
|
|
fixed: undefined,
|
|
|
@@ -232,153 +85,6 @@ Ext.define('Ext.grid.feature.Summary', {
|
|
|
me.bindStore(grid, grid.getStore());
|
|
|
},
|
|
|
|
|
|
- onBeforeReconfigure: function (grid, store) {
|
|
|
- this.summaryRecord = null;
|
|
|
-
|
|
|
- if (store) {
|
|
|
- this.bindStore(grid, store);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- bindStore: function (grid, store) {
|
|
|
- var me = this;
|
|
|
-
|
|
|
- Ext.destroy(me.storeListeners);
|
|
|
- me.storeListeners = store.on({
|
|
|
- scope: me,
|
|
|
- destroyable: true,
|
|
|
- update: me.onStoreUpdate,
|
|
|
- datachanged: me.onStoreUpdate
|
|
|
- });
|
|
|
-
|
|
|
- me.callParent([grid, store]);
|
|
|
- },
|
|
|
-
|
|
|
- renderSummaryRow: function (values, out, parent) {
|
|
|
- var view = values.view,
|
|
|
- me = view.findFeature('summary'),
|
|
|
- record;
|
|
|
-
|
|
|
- // If we get to here we won't be buffered
|
|
|
- if (!me.disabled && me.showSummaryRow && !view.addingRows && !view.updatingRows) {
|
|
|
- record = me.summaryRecord;
|
|
|
-
|
|
|
- out.push('<table cellpadding="0" cellspacing="0" class="' + me.summaryItemCls + '" style="table-layout: fixed; width: 100%;">');
|
|
|
- me.outputSummaryRecord((record && record.isModel) ? record : me.createSummaryRecord(view), values, out, parent);
|
|
|
- out.push('</table>');
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- toggleSummaryRow: function (visible, fromLockingPartner) {
|
|
|
- var me = this,
|
|
|
- bar = me.summaryBar;
|
|
|
-
|
|
|
- me.callParent([visible, fromLockingPartner]);
|
|
|
- if (bar) {
|
|
|
- bar.setVisible(me.showSummaryRow);
|
|
|
- me.onViewScroll();
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- getSummaryBar: function () {
|
|
|
- return this.summaryBar;
|
|
|
- },
|
|
|
-
|
|
|
- getSummaryRowPlaceholder: function (view) {
|
|
|
- var placeholderCls = this.summaryItemCls,
|
|
|
- nodeContainer, row;
|
|
|
-
|
|
|
- nodeContainer = Ext.fly(view.getNodeContainer());
|
|
|
-
|
|
|
- if (!nodeContainer) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- row = nodeContainer.down('.' + placeholderCls, true);
|
|
|
-
|
|
|
- if (!row) {
|
|
|
- row = nodeContainer.createChild({
|
|
|
- tag: 'table',
|
|
|
- cellpadding: 0,
|
|
|
- cellspacing: 0,
|
|
|
- cls: placeholderCls,
|
|
|
- style: 'table-layout: fixed; width: 100%',
|
|
|
- children: [{
|
|
|
- tag: 'tbody' // Ensure tBodies property is present on the row
|
|
|
- }]
|
|
|
- }, false, true);
|
|
|
- }
|
|
|
-
|
|
|
- return row;
|
|
|
- },
|
|
|
-
|
|
|
- vetoEvent: function (record, row, rowIndex, e) {
|
|
|
- return !e.getTarget(this.summaryRowSelector);
|
|
|
- },
|
|
|
-
|
|
|
- onViewScroll: function () {
|
|
|
- this.summaryBar.setScrollX(this.view.getScrollX());
|
|
|
- },
|
|
|
-
|
|
|
- onViewRefresh: function (view) {
|
|
|
- var me = this,
|
|
|
- record, row;
|
|
|
-
|
|
|
- // Only add this listener if in buffered mode, if there are no rows then
|
|
|
- // we won't have anything rendered, so we need to push the row in here
|
|
|
- if (!me.disabled && me.showSummaryRow && !view.all.getCount()) {
|
|
|
- record = me.createSummaryRecord(view);
|
|
|
- row = me.getSummaryRowPlaceholder(view);
|
|
|
- row.tBodies[0].appendChild(view.createRowElement(record, -1).querySelector(me.summaryRowSelector));
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- createSummaryRecord: function (view) {
|
|
|
- var me = this,
|
|
|
- columns = view.headerCt.getGridColumns(),
|
|
|
- remoteRoot = me.remoteRoot,
|
|
|
- summaryRecord = me.summaryRecord || (me.summaryRecord = new Ext.data.Model({
|
|
|
- id: view.id + '-summary-record'
|
|
|
- })),
|
|
|
- colCount = columns.length,
|
|
|
- i, column,
|
|
|
- dataIndex, summaryValue;
|
|
|
-
|
|
|
- // Set the summary field values
|
|
|
- summaryRecord.beginEdit();
|
|
|
-
|
|
|
- if (remoteRoot) {
|
|
|
- summaryValue = me.generateSummaryData();
|
|
|
-
|
|
|
- if (summaryValue) {
|
|
|
- summaryRecord.set(summaryValue);
|
|
|
- }
|
|
|
- } else {
|
|
|
- for (i = 0; i < colCount; i++) {
|
|
|
- column = columns[i];
|
|
|
-
|
|
|
- // In summary records, if there's no dataIndex, then the value in regular rows must come from a renderer.
|
|
|
- // We set the data value in using the column ID.
|
|
|
- dataIndex = column.dataIndex || column.getItemId();
|
|
|
-
|
|
|
- // We need to capture this value because it could get overwritten when setting on the model if there
|
|
|
- // is a convert() method on the model.
|
|
|
- summaryValue = me.getSummary(view.store, column.summaryType, dataIndex);
|
|
|
- summaryRecord.set(dataIndex, summaryValue);
|
|
|
-
|
|
|
- // Capture the columnId:value for the summaryRenderer in the summaryData object.
|
|
|
- me.setSummaryData(summaryRecord, column.getItemId(), summaryValue);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- summaryRecord.endEdit(true);
|
|
|
- // It's not dirty
|
|
|
- summaryRecord.commit(true);
|
|
|
- summaryRecord.isSummary = true;
|
|
|
-
|
|
|
- return summaryRecord;
|
|
|
- },
|
|
|
-
|
|
|
onStoreUpdate: function () {
|
|
|
var me = this,
|
|
|
view = me.view,
|
|
|
@@ -494,10 +200,4 @@ Ext.define('Ext.grid.feature.Summary', {
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
- destroy: function () {
|
|
|
- var me = this;
|
|
|
- me.summaryRecord = me.storeListeners = Ext.destroy(me.storeListeners);
|
|
|
- me.callParent();
|
|
|
- }
|
|
|
});
|