<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-grid-feature-Summary'>/**
|
</span> * 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
|
*
|
* ## 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',
|
|
<span id='Ext-grid-feature-Summary-cfg-dock'> /**
|
</span> * @cfg {String} dock
|
* Configure `'top'` or `'bottom'` top create a fixed summary row either above or below the scrollable table.
|
*
|
*/
|
dock: undefined,
|
|
<span id='Ext-grid-feature-Summary-property-dockedSummaryCls'> dockedSummaryCls: Ext.baseCSSPrefix + 'docked-summary',
|
</span>
|
<span id='Ext-grid-feature-Summary-property-panelBodyCls'> panelBodyCls: Ext.baseCSSPrefix + 'summary-',
|
</span>
|
<span id='Ext-grid-feature-Summary-method-init'> init: function(grid) {
|
</span> var me = this,
|
view = me.view;
|
|
me.callParent(arguments);
|
|
if (me.dock) {
|
grid.headerCt.on({
|
afterlayout: me.onStoreUpdate,
|
scope: me
|
});
|
grid.on({
|
beforerender: function() {
|
var tableCls = [me.summaryTableCls];
|
if (view.columnLines) {
|
tableCls[tableCls.length] = view.ownerCt.colLinesCls;
|
}
|
me.summaryBar = grid.addDocked({
|
childEls: ['innerCt'],
|
renderTpl: [
|
'<div id="{id}-innerCt">',
|
'<table cellPadding="0" cellSpacing="0" class="' + tableCls.join(' ') + '">',
|
'<tr class="' + me.summaryRowCls + '"></tr>',
|
'</table>',
|
'</div>'
|
],
|
style: 'overflow:hidden',
|
itemId: 'summaryBar',
|
cls: [ me.dockedSummaryCls, me.dockedSummaryCls + '-' + me.dock ],
|
xtype: 'component',
|
dock: me.dock,
|
weight: 10000000
|
})[0];
|
},
|
afterrender: function() {
|
grid.body.addCls(me.panelBodyCls + me.dock);
|
view.mon(view.el, {
|
scroll: me.onViewScroll,
|
scope: me
|
});
|
me.onStoreUpdate();
|
},
|
single: true
|
});
|
|
// Stretch the innerCt of the summary bar upon headerCt layout
|
grid.headerCt.afterComponentLayout = Ext.Function.createSequence(grid.headerCt.afterComponentLayout, function() {
|
me.summaryBar.innerCt.setWidth(this.getFullWidth() + Ext.getScrollbarSize().width);
|
});
|
} else {
|
me.view.addFooterFn(me.renderTFoot);
|
}
|
|
grid.on({
|
columnmove: me.onStoreUpdate,
|
scope: me
|
});
|
|
// On change of data, we have to update the docked summary.
|
view.mon(view.store, {
|
update: me.onStoreUpdate,
|
datachanged: me.onStoreUpdate,
|
scope: me
|
});
|
},
|
|
<span id='Ext-grid-feature-Summary-method-renderTFoot'> renderTFoot: function(values, out) {
|
</span> var view = values.view,
|
me = view.findFeature('summary');
|
|
if (me.showSummaryRow) {
|
out.push('<tfoot>');
|
me.outputSummaryRecord(me.createSummaryRecord(view), values, out);
|
out.push('</tfoot>');
|
}
|
},
|
|
<span id='Ext-grid-feature-Summary-method-vetoEvent'> vetoEvent: function(record, row, rowIndex, e) {
|
</span> return !e.getTarget(this.summaryRowSelector);
|
},
|
|
<span id='Ext-grid-feature-Summary-method-onViewScroll'> onViewScroll: function() {
|
</span> this.summaryBar.el.dom.scrollLeft = this.view.el.dom.scrollLeft;
|
},
|
|
<span id='Ext-grid-feature-Summary-method-createSummaryRecord'> createSummaryRecord: function(view) {
|
</span> var columns = view.headerCt.getVisibleGridColumns(),
|
info = {
|
records: view.store.getRange()
|
},
|
colCount = columns.length, i, column,
|
summaryRecord = this.summaryRecord || (this.summaryRecord = new view.store.model(null, view.id + '-summary-record'));
|
|
// Set the summary field values
|
summaryRecord.beginEdit();
|
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.
|
if (!column.dataIndex) {
|
column.dataIndex = column.id;
|
}
|
|
summaryRecord.set(column.dataIndex, this.getSummary(view.store, column.summaryType, column.dataIndex, info));
|
}
|
summaryRecord.endEdit(true);
|
// It's not dirty
|
summaryRecord.commit(true);
|
summaryRecord.isSummary = true;
|
|
return summaryRecord;
|
},
|
|
<span id='Ext-grid-feature-Summary-method-onStoreUpdate'> onStoreUpdate: function() {
|
</span> var me = this,
|
view = me.view,
|
record = me.createSummaryRecord(view),
|
newRowDom = view.createRowElement(record, -1),
|
oldRowDom, partner,
|
p;
|
|
if (!view.rendered) {
|
return;
|
}
|
|
// Summary row is inside the docked summaryBar Component
|
if (me.dock) {
|
oldRowDom = me.summaryBar.el.down('.' + me.summaryRowCls, true);
|
}
|
// Summary row is a regular row in a THEAD inside the View.
|
// Downlinked through the summary record's ID'
|
else {
|
oldRowDom = me.view.getNode(record);
|
}
|
|
if (oldRowDom) {
|
p = oldRowDom.parentNode;
|
p.insertBefore(newRowDom, oldRowDom);
|
p.removeChild(oldRowDom);
|
|
partner = me.lockingPartner;
|
// For locking grids...
|
// Update summary on other side (unless we have been called from the other side)
|
if (partner && partner.grid.rendered && !me.calledFromLockingPartner) {
|
partner.calledFromLockingPartner = true;
|
partner.onStoreUpdate();
|
partner.calledFromLockingPartner = false;
|
}
|
}
|
// If docked, the updated row will need sizing because it's outside the View
|
if (me.dock) {
|
me.onColumnHeaderLayout();
|
}
|
},
|
|
<span id='Ext-grid-feature-Summary-method-onColumnHeaderLayout'> // Synchronize column widths in the docked summary Component
|
</span> onColumnHeaderLayout: function() {
|
var view = this.view,
|
columns = view.headerCt.getVisibleGridColumns(),
|
column,
|
len = columns.length, i,
|
summaryEl = this.summaryBar.el,
|
el;
|
|
for (i = 0; i < len; i++) {
|
column = columns[i];
|
el = summaryEl.down(view.getCellSelector(column));
|
if (el) {
|
if (column.hidden) {
|
el.setDisplayed(false);
|
} else {
|
el.setDisplayed(true);
|
el.setWidth(column.width || (column.lastBox ? column.lastBox.width : 100));
|
}
|
}
|
}
|
}
|
});</pre>
|
</body>
|
</html>
|