commit extjs-2.2.1
[extjs.git] / examples / grid / GroupSummary.js
1 /*\r
2  * Ext JS Library 2.2.1\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 Ext.grid.GroupSummary = function(config){\r
10     Ext.apply(this, config);\r
11 };\r
12 \r
13 Ext.extend(Ext.grid.GroupSummary, Ext.util.Observable, {\r
14     init : function(grid){\r
15         this.grid = grid;\r
16         this.cm = grid.getColumnModel();\r
17         this.view = grid.getView();\r
18 \r
19         var v = this.view;\r
20         v.doGroupEnd = this.doGroupEnd.createDelegate(this);\r
21 \r
22         v.afterMethod('onColumnWidthUpdated', this.doWidth, this);\r
23         v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);\r
24         v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);\r
25         v.afterMethod('onUpdate', this.doUpdate, this);\r
26         v.afterMethod('onRemove', this.doRemove, this);\r
27 \r
28         if(!this.rowTpl){\r
29             this.rowTpl = new Ext.Template(\r
30                 '<div class="x-grid3-summary-row" style="{tstyle}">',\r
31                 '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
32                     '<tbody><tr>{cells}</tr></tbody>',\r
33                 '</table></div>'\r
34             );\r
35             this.rowTpl.disableFormats = true;\r
36         }\r
37         this.rowTpl.compile();\r
38 \r
39         if(!this.cellTpl){\r
40             this.cellTpl = new Ext.Template(\r
41                 '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',\r
42                 '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on">{value}</div>',\r
43                 "</td>"\r
44             );\r
45             this.cellTpl.disableFormats = true;\r
46         }\r
47         this.cellTpl.compile();\r
48     },\r
49 \r
50     toggleSummaries : function(visible){\r
51         var el = this.grid.getGridEl();\r
52         if(el){\r
53             if(visible === undefined){\r
54                 visible = el.hasClass('x-grid-hide-summary');\r
55             }\r
56             el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');\r
57         }\r
58     },\r
59 \r
60     renderSummary : function(o, cs){\r
61         cs = cs || this.view.getColumnData();\r
62         var cfg = this.cm.config;\r
63 \r
64         var buf = [], c, p = {}, cf, last = cs.length-1;\r
65         for(var i = 0, len = cs.length; i < len; i++){\r
66             c = cs[i];\r
67             cf = cfg[i];\r
68             p.id = c.id;\r
69             p.style = c.style;\r
70             p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
71             if(cf.summaryType || cf.summaryRenderer){\r
72                 p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o);\r
73             }else{\r
74                 p.value = '';\r
75             }\r
76             if(p.value == undefined || p.value === "") p.value = "&#160;";\r
77             buf[buf.length] = this.cellTpl.apply(p);\r
78         }\r
79 \r
80         return this.rowTpl.apply({\r
81             tstyle: 'width:'+this.view.getTotalWidth()+';',\r
82             cells: buf.join('')\r
83         });\r
84     },\r
85 \r
86     calculate : function(rs, cs){\r
87         var data = {}, r, c, cfg = this.cm.config, cf;\r
88         for(var j = 0, jlen = rs.length; j < jlen; j++){\r
89             r = rs[j];\r
90             for(var i = 0, len = cs.length; i < len; i++){\r
91                 c = cs[i];\r
92                 cf = cfg[i];\r
93                 if(cf.summaryType){\r
94                     data[c.name] = Ext.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data);\r
95                 }\r
96             }\r
97         }\r
98         return data;\r
99     },\r
100 \r
101     doGroupEnd : function(buf, g, cs, ds, colCount){\r
102         var data = this.calculate(g.rs, cs);\r
103         buf.push('</div>', this.renderSummary({data: data}, cs), '</div>');\r
104     },\r
105 \r
106     doWidth : function(col, w, tw){\r
107         var gs = this.view.getGroups(), s;\r
108         for(var i = 0, len = gs.length; i < len; i++){\r
109             s = gs[i].childNodes[2];\r
110             s.style.width = tw;\r
111             s.firstChild.style.width = tw;\r
112             s.firstChild.rows[0].childNodes[col].style.width = w;\r
113         }\r
114     },\r
115 \r
116     doAllWidths : function(ws, tw){\r
117         var gs = this.view.getGroups(), s, cells, wlen = ws.length;\r
118         for(var i = 0, len = gs.length; i < len; i++){\r
119             s = gs[i].childNodes[2];\r
120             s.style.width = tw;\r
121             s.firstChild.style.width = tw;\r
122             cells = s.firstChild.rows[0].childNodes;\r
123             for(var j = 0; j < wlen; j++){\r
124                 cells[j].style.width = ws[j];\r
125             }\r
126         }\r
127     },\r
128 \r
129     doHidden : function(col, hidden, tw){\r
130         var gs = this.view.getGroups(), s, display = hidden ? 'none' : '';\r
131         for(var i = 0, len = gs.length; i < len; i++){\r
132             s = gs[i].childNodes[2];\r
133             s.style.width = tw;\r
134             s.firstChild.style.width = tw;\r
135             s.firstChild.rows[0].childNodes[col].style.display = display;\r
136         }\r
137     },\r
138 \r
139     // Note: requires that all (or the first) record in the \r
140     // group share the same group value. Returns false if the group\r
141     // could not be found.\r
142     refreshSummary : function(groupValue){\r
143         return this.refreshSummaryById(this.view.getGroupId(groupValue));\r
144     },\r
145 \r
146     getSummaryNode : function(gid){\r
147         var g = Ext.fly(gid, '_gsummary');\r
148         if(g){\r
149             return g.down('.x-grid3-summary-row', true);\r
150         }\r
151         return null;\r
152     },\r
153 \r
154     refreshSummaryById : function(gid){\r
155         var g = document.getElementById(gid);\r
156         if(!g){\r
157             return false;\r
158         }\r
159         var rs = [];\r
160         this.grid.store.each(function(r){\r
161             if(r._groupId == gid){\r
162                 rs[rs.length] = r;\r
163             }\r
164         });\r
165         var cs = this.view.getColumnData();\r
166         var data = this.calculate(rs, cs);\r
167         var markup = this.renderSummary({data: data}, cs);\r
168 \r
169         var existing = this.getSummaryNode(gid);\r
170         if(existing){\r
171             g.removeChild(existing);\r
172         }\r
173         Ext.DomHelper.append(g, markup);\r
174         return true;\r
175     },\r
176 \r
177     doUpdate : function(ds, record){\r
178         this.refreshSummaryById(record._groupId);\r
179     },\r
180 \r
181     doRemove : function(ds, record, index, isUpdate){\r
182         if(!isUpdate){\r
183             this.refreshSummaryById(record._groupId);\r
184         }\r
185     },\r
186 \r
187     showSummaryMsg : function(groupValue, msg){\r
188         var gid = this.view.getGroupId(groupValue);\r
189         var node = this.getSummaryNode(gid);\r
190         if(node){\r
191             node.innerHTML = '<div class="x-grid3-summary-msg">' + msg + '</div>';\r
192         }\r
193     }\r
194 });\r
195 \r
196 Ext.grid.GroupSummary.Calculations = {\r
197     'sum' : function(v, record, field){\r
198         return v + (record.data[field]||0);\r
199     },\r
200 \r
201     'count' : function(v, record, field, data){\r
202         return data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);\r
203     },\r
204 \r
205     'max' : function(v, record, field, data){\r
206         var v = record.data[field];\r
207         var max = data[field+'max'] === undefined ? (data[field+'max'] = v) : data[field+'max'];\r
208         return v > max ? (data[field+'max'] = v) : max;\r
209     },\r
210 \r
211     'min' : function(v, record, field, data){\r
212         var v = record.data[field];\r
213         var min = data[field+'min'] === undefined ? (data[field+'min'] = v) : data[field+'min'];\r
214         return v < min ? (data[field+'min'] = v) : min;\r
215     },\r
216 \r
217     'average' : function(v, record, field, data){\r
218         var c = data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);\r
219         var t = (data[field+'total'] = ((data[field+'total']||0) + (record.data[field]||0)));\r
220         return t === 0 ? 0 : t / c;\r
221     }\r
222 }\r
223 \r
224 Ext.grid.HybridSummary = Ext.extend(Ext.grid.GroupSummary, {\r
225     calculate : function(rs, cs){\r
226         var gcol = this.view.getGroupField();\r
227         var gvalue = rs[0].data[gcol];\r
228         var gdata = this.getSummaryData(gvalue);\r
229         return gdata || Ext.grid.HybridSummary.superclass.calculate.call(this, rs, cs);\r
230     },\r
231 \r
232     updateSummaryData : function(groupValue, data, skipRefresh){\r
233         var json = this.grid.store.reader.jsonData;\r
234         if(!json.summaryData){\r
235             json.summaryData = {};\r
236         }\r
237         json.summaryData[groupValue] = data;\r
238         if(!skipRefresh){\r
239             this.refreshSummary(groupValue);\r
240         }\r
241     },\r
242 \r
243     getSummaryData : function(groupValue){\r
244         var json = this.grid.store.reader.jsonData;\r
245         if(json && json.summaryData){\r
246             return json.summaryData[groupValue];\r
247         }\r
248         return null;\r
249     }\r
250 });