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