Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / GroupSummary.html
1 <html>\r
2 <head>\r
3   <title>The source code</title>\r
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
6 </head>\r
7 <body  onload="prettyPrint();">\r
8     <pre class="prettyprint lang-js">Ext.ns('Ext.ux.grid');\r
9 \r
10 <div id="cls-Ext.ux.grid.GroupSummary"></div>/**\r
11  * @class Ext.ux.grid.GroupSummary\r
12  * @extends Ext.util.Observable\r
13  * A GridPanel plugin that enables dynamic column calculations and a dynamically\r
14  * updated grouped summary row.\r
15  */\r
16 Ext.ux.grid.GroupSummary = Ext.extend(Ext.util.Observable, {\r
17     <div id="cfg-Ext.ux.grid.GroupSummary-summaryRenderer"></div>/**\r
18      * @cfg {Function} summaryRenderer Renderer example:<pre><code>\r
19 summaryRenderer: function(v, params, data){\r
20     return ((v === 0 || v > 1) ? '(' + v +' Tasks)' : '(1 Task)');\r
21 },\r
22      * </code></pre>\r
23      */\r
24     <div id="cfg-Ext.ux.grid.GroupSummary-summaryType"></div>/**\r
25      * @cfg {String} summaryType (Optional) The type of\r
26      * calculation to be used for the column.  For options available see\r
27      * {@link #Calculations}.\r
28      */\r
29 \r
30     constructor : function(config){\r
31         Ext.apply(this, config);\r
32         Ext.ux.grid.GroupSummary.superclass.constructor.call(this);\r
33     },\r
34     init : function(grid){\r
35         this.grid = grid;\r
36         this.cm = grid.getColumnModel();\r
37         this.view = grid.getView();\r
38 \r
39         var v = this.view;\r
40         v.doGroupEnd = this.doGroupEnd.createDelegate(this);\r
41 \r
42         v.afterMethod('onColumnWidthUpdated', this.doWidth, this);\r
43         v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);\r
44         v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);\r
45         v.afterMethod('onUpdate', this.doUpdate, this);\r
46         v.afterMethod('onRemove', this.doRemove, this);\r
47 \r
48         if(!this.rowTpl){\r
49             this.rowTpl = new Ext.Template(\r
50                 '<div class="x-grid3-summary-row" style="{tstyle}">',\r
51                 '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
52                     '<tbody><tr>{cells}</tr></tbody>',\r
53                 '</table></div>'\r
54             );\r
55             this.rowTpl.disableFormats = true;\r
56         }\r
57         this.rowTpl.compile();\r
58 \r
59         if(!this.cellTpl){\r
60             this.cellTpl = new Ext.Template(\r
61                 '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',\r
62                 '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on">{value}</div>',\r
63                 "</td>"\r
64             );\r
65             this.cellTpl.disableFormats = true;\r
66         }\r
67         this.cellTpl.compile();\r
68     },\r
69 \r
70     <div id="method-Ext.ux.grid.GroupSummary-toggleSummaries"></div>/**\r
71      * Toggle the display of the summary row on/off\r
72      * @param {Boolean} visible <tt>true</tt> to show the summary, <tt>false</tt> to hide the summary.\r
73      */\r
74     toggleSummaries : function(visible){\r
75         var el = this.grid.getGridEl();\r
76         if(el){\r
77             if(visible === undefined){\r
78                 visible = el.hasClass('x-grid-hide-summary');\r
79             }\r
80             el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');\r
81         }\r
82     },\r
83 \r
84     renderSummary : function(o, cs){\r
85         cs = cs || this.view.getColumnData();\r
86         var cfg = this.cm.config;\r
87 \r
88         var buf = [], c, p = {}, cf, last = cs.length-1;\r
89         for(var i = 0, len = cs.length; i < len; i++){\r
90             c = cs[i];\r
91             cf = cfg[i];\r
92             p.id = c.id;\r
93             p.style = c.style;\r
94             p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
95             if(cf.summaryType || cf.summaryRenderer){\r
96                 p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o);\r
97             }else{\r
98                 p.value = '';\r
99             }\r
100             if(p.value == undefined || p.value === "") p.value = "&#160;";\r
101             buf[buf.length] = this.cellTpl.apply(p);\r
102         }\r
103 \r
104         return this.rowTpl.apply({\r
105             tstyle: 'width:'+this.view.getTotalWidth()+';',\r
106             cells: buf.join('')\r
107         });\r
108     },\r
109 \r
110     /**\r
111      * @private\r
112      * @param {Object} rs\r
113      * @param {Object} cs\r
114      */\r
115     calculate : function(rs, cs){\r
116         var data = {}, r, c, cfg = this.cm.config, cf;\r
117         for(var j = 0, jlen = rs.length; j < jlen; j++){\r
118             r = rs[j];\r
119             for(var i = 0, len = cs.length; i < len; i++){\r
120                 c = cs[i];\r
121                 cf = cfg[i];\r
122                 if(cf.summaryType){\r
123                     data[c.name] = Ext.ux.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data);\r
124                 }\r
125             }\r
126         }\r
127         return data;\r
128     },\r
129 \r
130     doGroupEnd : function(buf, g, cs, ds, colCount){\r
131         var data = this.calculate(g.rs, cs);\r
132         buf.push('</div>', this.renderSummary({data: data}, cs), '</div>');\r
133     },\r
134 \r
135     doWidth : function(col, w, tw){\r
136         var gs = this.view.getGroups(), s;\r
137         for(var i = 0, len = gs.length; i < len; i++){\r
138             s = gs[i].childNodes[2];\r
139             s.style.width = tw;\r
140             s.firstChild.style.width = tw;\r
141             s.firstChild.rows[0].childNodes[col].style.width = w;\r
142         }\r
143     },\r
144 \r
145     doAllWidths : function(ws, tw){\r
146         var gs = this.view.getGroups(), s, cells, wlen = ws.length;\r
147         for(var i = 0, len = gs.length; i < len; i++){\r
148             s = gs[i].childNodes[2];\r
149             s.style.width = tw;\r
150             s.firstChild.style.width = tw;\r
151             cells = s.firstChild.rows[0].childNodes;\r
152             for(var j = 0; j < wlen; j++){\r
153                 cells[j].style.width = ws[j];\r
154             }\r
155         }\r
156     },\r
157 \r
158     doHidden : function(col, hidden, tw){\r
159         var gs = this.view.getGroups(), s, display = hidden ? 'none' : '';\r
160         for(var i = 0, len = gs.length; i < len; i++){\r
161             s = gs[i].childNodes[2];\r
162             s.style.width = tw;\r
163             s.firstChild.style.width = tw;\r
164             s.firstChild.rows[0].childNodes[col].style.display = display;\r
165         }\r
166     },\r
167 \r
168     // Note: requires that all (or the first) record in the\r
169     // group share the same group value. Returns false if the group\r
170     // could not be found.\r
171     refreshSummary : function(groupValue){\r
172         return this.refreshSummaryById(this.view.getGroupId(groupValue));\r
173     },\r
174 \r
175     getSummaryNode : function(gid){\r
176         var g = Ext.fly(gid, '_gsummary');\r
177         if(g){\r
178             return g.down('.x-grid3-summary-row', true);\r
179         }\r
180         return null;\r
181     },\r
182 \r
183     refreshSummaryById : function(gid){\r
184         var g = document.getElementById(gid);\r
185         if(!g){\r
186             return false;\r
187         }\r
188         var rs = [];\r
189         this.grid.store.each(function(r){\r
190             if(r._groupId == gid){\r
191                 rs[rs.length] = r;\r
192             }\r
193         });\r
194         var cs = this.view.getColumnData();\r
195         var data = this.calculate(rs, cs);\r
196         var markup = this.renderSummary({data: data}, cs);\r
197 \r
198         var existing = this.getSummaryNode(gid);\r
199         if(existing){\r
200             g.removeChild(existing);\r
201         }\r
202         Ext.DomHelper.append(g, markup);\r
203         return true;\r
204     },\r
205 \r
206     doUpdate : function(ds, record){\r
207         this.refreshSummaryById(record._groupId);\r
208     },\r
209 \r
210     doRemove : function(ds, record, index, isUpdate){\r
211         if(!isUpdate){\r
212             this.refreshSummaryById(record._groupId);\r
213         }\r
214     },\r
215 \r
216     <div id="method-Ext.ux.grid.GroupSummary-showSummaryMsg"></div>/**\r
217      * Show a message in the summary row.\r
218      * <pre><code>\r
219 grid.on('afteredit', function(){\r
220     var groupValue = 'Ext Forms: Field Anchoring';\r
221     summary.showSummaryMsg(groupValue, 'Updating Summary...');\r
222 });\r
223      * </code></pre>\r
224      * @param {String} groupValue\r
225      * @param {String} msg Text to use as innerHTML for the summary row.\r
226      */\r
227     showSummaryMsg : function(groupValue, msg){\r
228         var gid = this.view.getGroupId(groupValue);\r
229         var node = this.getSummaryNode(gid);\r
230         if(node){\r
231             node.innerHTML = '<div class="x-grid3-summary-msg">' + msg + '</div>';\r
232         }\r
233     }\r
234 });\r
235 \r
236 //backwards compat\r
237 Ext.grid.GroupSummary = Ext.ux.grid.GroupSummary;\r
238 \r
239 \r
240 <div id="prop-Ext.ux.grid.GroupSummary-Calculations"></div>/**\r
241  * Calculation types for summary row:</p><div class="mdetail-params"><ul>\r
242  * <li><b><tt>sum</tt></b> : <div class="sub-desc"></div></li>\r
243  * <li><b><tt>count</tt></b> : <div class="sub-desc"></div></li>\r
244  * <li><b><tt>max</tt></b> : <div class="sub-desc"></div></li>\r
245  * <li><b><tt>min</tt></b> : <div class="sub-desc"></div></li>\r
246  * <li><b><tt>average</tt></b> : <div class="sub-desc"></div></li>\r
247  * </ul></div>\r
248  * <p>Custom calculations may be implemented.  An example of\r
249  * custom <code>summaryType=totalCost</code>:</p><pre><code>\r
250 // define a custom summary function\r
251 Ext.ux.grid.GroupSummary.Calculations['totalCost'] = function(v, record, field){\r
252     return v + (record.data.estimate * record.data.rate);\r
253 };\r
254  * </code></pre>\r
255  * @property Calculations\r
256  */\r
257 \r
258 Ext.ux.grid.GroupSummary.Calculations = {\r
259     'sum' : function(v, record, field){\r
260         return v + (record.data[field]||0);\r
261     },\r
262 \r
263     'count' : function(v, record, field, data){\r
264         return data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);\r
265     },\r
266 \r
267     'max' : function(v, record, field, data){\r
268         var v = record.data[field];\r
269         var max = data[field+'max'] === undefined ? (data[field+'max'] = v) : data[field+'max'];\r
270         return v > max ? (data[field+'max'] = v) : max;\r
271     },\r
272 \r
273     'min' : function(v, record, field, data){\r
274         var v = record.data[field];\r
275         var min = data[field+'min'] === undefined ? (data[field+'min'] = v) : data[field+'min'];\r
276         return v < min ? (data[field+'min'] = v) : min;\r
277     },\r
278 \r
279     'average' : function(v, record, field, data){\r
280         var c = data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);\r
281         var t = (data[field+'total'] = ((data[field+'total']||0) + (record.data[field]||0)));\r
282         return t === 0 ? 0 : t / c;\r
283     }\r
284 };\r
285 Ext.grid.GroupSummary.Calculations = Ext.ux.grid.GroupSummary.Calculations;\r
286 \r
287 <div id="cls-Ext.ux.grid.HybridSummary"></div>/**\r
288  * @class Ext.ux.grid.HybridSummary\r
289  * @extends Ext.ux.grid.GroupSummary\r
290  * Adds capability to specify the summary data for the group via json as illustrated here:\r
291  * <pre><code>\r
292 {\r
293     data: [\r
294         {\r
295             projectId: 100,     project: 'House',\r
296             taskId:    112, description: 'Paint',\r
297             estimate:    6,        rate:     150,\r
298             due:'06/24/2007'\r
299         },\r
300         ...\r
301     ],\r
302 \r
303     summaryData: {\r
304         'House': {\r
305             description: 14, estimate: 9,\r
306                    rate: 99, due: new Date(2009, 6, 29),\r
307                    cost: 999\r
308         }\r
309     }\r
310 }\r
311  * </code></pre>\r
312  *\r
313  */\r
314 Ext.ux.grid.HybridSummary = Ext.extend(Ext.ux.grid.GroupSummary, {\r
315     /**\r
316      * @private\r
317      * @param {Object} rs\r
318      * @param {Object} cs\r
319      */\r
320     calculate : function(rs, cs){\r
321         var gcol = this.view.getGroupField();\r
322         var gvalue = rs[0].data[gcol];\r
323         var gdata = this.getSummaryData(gvalue);\r
324         return gdata || Ext.ux.grid.HybridSummary.superclass.calculate.call(this, rs, cs);\r
325     },\r
326 \r
327     <div id="method-Ext.ux.grid.HybridSummary-updateSummaryData"></div>/**\r
328      * <pre><code>\r
329 grid.on('afteredit', function(){\r
330     var groupValue = 'Ext Forms: Field Anchoring';\r
331     summary.showSummaryMsg(groupValue, 'Updating Summary...');\r
332     setTimeout(function(){ // simulate server call\r
333         // HybridSummary class implements updateSummaryData\r
334         summary.updateSummaryData(groupValue,\r
335             // create data object based on configured dataIndex\r
336             {description: 22, estimate: 888, rate: 888, due: new Date(), cost: 8});\r
337     }, 2000);\r
338 });\r
339      * </code></pre>\r
340      * @param {String} groupValue\r
341      * @param {Object} data data object\r
342      * @param {Boolean} skipRefresh (Optional) Defaults to false\r
343      */\r
344     updateSummaryData : function(groupValue, data, skipRefresh){\r
345         var json = this.grid.store.reader.jsonData;\r
346         if(!json.summaryData){\r
347             json.summaryData = {};\r
348         }\r
349         json.summaryData[groupValue] = data;\r
350         if(!skipRefresh){\r
351             this.refreshSummary(groupValue);\r
352         }\r
353     },\r
354 \r
355     <div id="method-Ext.ux.grid.HybridSummary-getSummaryData"></div>/**\r
356      * Returns the summaryData for the specified groupValue or null.\r
357      * @param {String} groupValue\r
358      * @return {Object} summaryData\r
359      */\r
360     getSummaryData : function(groupValue){\r
361         var json = this.grid.store.reader.jsonData;\r
362         if(json && json.summaryData){\r
363             return json.summaryData[groupValue];\r
364         }\r
365         return null;\r
366     }\r
367 });\r
368 \r
369 //backwards compat\r
370 Ext.grid.HybridSummary = Ext.ux.grid.HybridSummary;\r
371 </pre>    \r
372 </body>\r
373 </html>