Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / src / grid / feature / Summary.js
1 /**
2  * @class Ext.grid.feature.Summary
3  * @extends Ext.grid.feature.AbstractSummary
4  * 
5  * This feature is used to place a summary row at the bottom of the grid. If using a grouping, 
6  * see {@link Ext.grid.feature.GroupingSummary}. There are 2 aspects to calculating the summaries, 
7  * calculation and rendering.
8  * 
9  * ## Calculation
10  * The summary value needs to be calculated for each column in the grid. This is controlled
11  * by the summaryType option specified on the column. There are several built in summary types,
12  * which can be specified as a string on the column configuration. These call underlying methods
13  * on the store:
14  *
15  *  - {@link Ext.data.Store#count count}
16  *  - {@link Ext.data.Store#sum sum}
17  *  - {@link Ext.data.Store#min min}
18  *  - {@link Ext.data.Store#max max}
19  *  - {@link Ext.data.Store#average average}
20  *
21  * Alternatively, the summaryType can be a function definition. If this is the case,
22  * the function is called with an array of records to calculate the summary value.
23  * 
24  * ## Rendering
25  * Similar to a column, the summary also supports a summaryRenderer function. This
26  * summaryRenderer is called before displaying a value. The function is optional, if
27  * not specified the default calculated value is shown. The summaryRenderer is called with:
28  *
29  *  - value {Object} - The calculated value.
30  *  - summaryData {Object} - Contains all raw summary values for the row.
31  *  - field {String} - The name of the field we are calculating
32  * 
33  * ## Example Usage
34  *
35  *     Ext.define('TestResult', {
36  *         extend: 'Ext.data.Model',
37  *         fields: ['student', {
38  *             name: 'mark',
39  *             type: 'int'
40  *         }]
41  *     });
42  *     
43  *     Ext.create('Ext.grid.Panel', {
44  *         width: 200,
45  *         height: 140,
46  *         renderTo: document.body,
47  *         features: [{
48  *             ftype: 'summary'
49  *         }],
50  *         store: {
51  *             model: 'TestResult',
52  *             data: [{
53  *                 student: 'Student 1',
54  *                 mark: 84
55  *             },{
56  *                 student: 'Student 2',
57  *                 mark: 72
58  *             },{
59  *                 student: 'Student 3',
60  *                 mark: 96
61  *             },{
62  *                 student: 'Student 4',
63  *                 mark: 68
64  *             }]
65  *         },
66  *         columns: [{
67  *             dataIndex: 'student',
68  *             text: 'Name',
69  *             summaryType: 'count',
70  *             summaryRenderer: function(value, summaryData, dataIndex) {
71  *                 return Ext.String.format('{0} student{1}', value, value !== 1 ? 's' : ''); 
72  *             }
73  *         }, {
74  *             dataIndex: 'mark',
75  *             text: 'Mark',
76  *             summaryType: 'average'
77  *         }]
78  *     });
79  */
80 Ext.define('Ext.grid.feature.Summary', {
81     
82     /* Begin Definitions */
83     
84     extend: 'Ext.grid.feature.AbstractSummary',
85     
86     alias: 'feature.summary',
87     
88     /* End Definitions */
89     
90     /**
91      * Gets any fragments needed for the template.
92      * @private
93      * @return {Object} The fragments
94      */
95     getFragmentTpl: function() {
96         // this gets called before render, so we'll setup the data here.
97         this.summaryData = this.generateSummaryData(); 
98         return this.getSummaryFragments();
99     },
100     
101     /**
102      * Overrides the closeRows method on the template so we can include our own custom
103      * footer.
104      * @private
105      * @return {Object} The custom fragments
106      */
107     getTableFragments: function(){
108         if (this.showSummaryRow) {
109             return {
110                 closeRows: this.closeRows
111             };
112         }
113     },
114     
115     /**
116      * Provide our own custom footer for the grid.
117      * @private
118      * @return {String} The custom footer
119      */
120     closeRows: function() {
121         return '</tpl>{[this.printSummaryRow()]}';
122     },
123     
124     /**
125      * Gets the data for printing a template row
126      * @private
127      * @param {Number} index The index in the template
128      * @return {Array} The template values
129      */
130     getPrintData: function(index){
131         var me = this,
132             columns = me.view.headerCt.getColumnsForTpl(),
133             i = 0,
134             length = columns.length,
135             data = [],
136             active = me.summaryData,
137             column;
138             
139         for (; i < length; ++i) {
140             column = columns[i];
141             column.gridSummaryValue = this.getColumnValue(column, active);
142             data.push(column);
143         }
144         return data;
145     },
146     
147     /**
148      * Generates all of the summary data to be used when processing the template
149      * @private
150      * @return {Object} The summary data
151      */
152     generateSummaryData: function(){
153         var me = this,
154             data = {},
155             store = me.view.store,
156             columns = me.view.headerCt.getColumnsForTpl(),
157             i = 0,
158             length = columns.length,
159             fieldData,
160             key,
161             comp;
162             
163         for (i = 0, length = columns.length; i < length; ++i) {
164             comp = Ext.getCmp(columns[i].id);
165             data[comp.dataIndex] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
166         }
167         return data;
168     }
169 });