Upgrade to ExtJS 4.0.7 - Released 10/19/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  *     @example
50  *     Ext.define('TestResult', {
51  *         extend: 'Ext.data.Model',
52  *         fields: ['student', {
53  *             name: 'mark',
54  *             type: 'int'
55  *         }]
56  *     });
57  *     
58  *     Ext.create('Ext.grid.Panel', {
59  *         width: 200,
60  *         height: 140,
61  *         renderTo: document.body,
62  *         features: [{
63  *             ftype: 'summary'
64  *         }],
65  *         store: {
66  *             model: 'TestResult',
67  *             data: [{
68  *                 student: 'Student 1',
69  *                 mark: 84
70  *             },{
71  *                 student: 'Student 2',
72  *                 mark: 72
73  *             },{
74  *                 student: 'Student 3',
75  *                 mark: 96
76  *             },{
77  *                 student: 'Student 4',
78  *                 mark: 68
79  *             }]
80  *         },
81  *         columns: [{
82  *             dataIndex: 'student',
83  *             text: 'Name',
84  *             summaryType: 'count',
85  *             summaryRenderer: function(value, summaryData, dataIndex) {
86  *                 return Ext.String.format('{0} student{1}', value, value !== 1 ? 's' : ''); 
87  *             }
88  *         }, {
89  *             dataIndex: 'mark',
90  *             text: 'Mark',
91  *             summaryType: 'average'
92  *         }]
93  *     });
94  */
95 Ext.define('Ext.grid.feature.Summary', {
96     
97     /* Begin Definitions */
98     
99     extend: 'Ext.grid.feature.AbstractSummary',
100     
101     alias: 'feature.summary',
102     
103     /* End Definitions */
104     
105     /**
106      * Gets any fragments needed for the template.
107      * @private
108      * @return {Object} The fragments
109      */
110     getFragmentTpl: function() {
111         // this gets called before render, so we'll setup the data here.
112         this.summaryData = this.generateSummaryData(); 
113         return this.getSummaryFragments();
114     },
115     
116     /**
117      * Overrides the closeRows method on the template so we can include our own custom
118      * footer.
119      * @private
120      * @return {Object} The custom fragments
121      */
122     getTableFragments: function(){
123         if (this.showSummaryRow) {
124             return {
125                 closeRows: this.closeRows
126             };
127         }
128     },
129     
130     /**
131      * Provide our own custom footer for the grid.
132      * @private
133      * @return {String} The custom footer
134      */
135     closeRows: function() {
136         return '</tpl>{[this.printSummaryRow()]}';
137     },
138     
139     /**
140      * Gets the data for printing a template row
141      * @private
142      * @param {Number} index The index in the template
143      * @return {Array} The template values
144      */
145     getPrintData: function(index){
146         var me = this,
147             columns = me.view.headerCt.getColumnsForTpl(),
148             i = 0,
149             length = columns.length,
150             data = [],
151             active = me.summaryData,
152             column;
153             
154         for (; i < length; ++i) {
155             column = columns[i];
156             column.gridSummaryValue = this.getColumnValue(column, active);
157             data.push(column);
158         }
159         return data;
160     },
161     
162     /**
163      * Generates all of the summary data to be used when processing the template
164      * @private
165      * @return {Object} The summary data
166      */
167     generateSummaryData: function(){
168         var me = this,
169             data = {},
170             store = me.view.store,
171             columns = me.view.headerCt.getColumnsForTpl(),
172             i = 0,
173             length = columns.length,
174             fieldData,
175             key,
176             comp;
177             
178         for (i = 0, length = columns.length; i < length; ++i) {
179             comp = Ext.getCmp(columns[i].id);
180             data[comp.id] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
181         }
182         return data;
183     }
184 });