source: trunk/web/addons/job_monarch/lib/extjs-30/examples/ux/GroupSummary.js @ 625

Last change on this file since 625 was 625, checked in by ramonb, 15 years ago

lib/extjs-30:

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