X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/2e847cf21b8ab9d15fa167b315ca5b2fa92638fc..6a7e4474cba9d8be4b2ec445e10f1691f7277c50:/examples/ux/GroupSummary.js diff --git a/examples/ux/GroupSummary.js b/examples/ux/GroupSummary.js index 0cfdd448..46267db7 100644 --- a/examples/ux/GroupSummary.js +++ b/examples/ux/GroupSummary.js @@ -1,365 +1,405 @@ /*! - * Ext JS Library 3.1.1 - * Copyright(c) 2006-2010 Ext JS, LLC + * Ext JS Library 3.2.0 + * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ -Ext.ns('Ext.ux.grid'); - -/** - * @class Ext.ux.grid.GroupSummary - * @extends Ext.util.Observable - * A GridPanel plugin that enables dynamic column calculations and a dynamically - * updated grouped summary row. - */ -Ext.ux.grid.GroupSummary = Ext.extend(Ext.util.Observable, { - /** - * @cfg {Function} summaryRenderer Renderer example:

-summaryRenderer: function(v, params, data){
-    return ((v === 0 || v > 1) ? '(' + v +' Tasks)' : '(1 Task)');
-},
-     * 
- */ - /** - * @cfg {String} summaryType (Optional) The type of - * calculation to be used for the column. For options available see - * {@link #Calculations}. - */ - - constructor : function(config){ - Ext.apply(this, config); - Ext.ux.grid.GroupSummary.superclass.constructor.call(this); - }, - init : function(grid){ - this.grid = grid; - var v = this.view = grid.getView(); - v.doGroupEnd = this.doGroupEnd.createDelegate(this); - - v.afterMethod('onColumnWidthUpdated', this.doWidth, this); - v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); - v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); - v.afterMethod('onUpdate', this.doUpdate, this); - v.afterMethod('onRemove', this.doRemove, this); - - if(!this.rowTpl){ - this.rowTpl = new Ext.Template( - '
', - '', - '{cells}', - '
' - ); - this.rowTpl.disableFormats = true; - } - this.rowTpl.compile(); - - if(!this.cellTpl){ - this.cellTpl = new Ext.Template( - '', - '
{value}
', - "" - ); - this.cellTpl.disableFormats = true; - } - this.cellTpl.compile(); - }, - - /** - * Toggle the display of the summary row on/off - * @param {Boolean} visible true to show the summary, false to hide the summary. - */ - toggleSummaries : function(visible){ - var el = this.grid.getGridEl(); - if(el){ - if(visible === undefined){ - visible = el.hasClass('x-grid-hide-summary'); - } - el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary'); - } - }, - - renderSummary : function(o, cs){ - cs = cs || this.view.getColumnData(); - var cfg = this.grid.getColumnModel().config, - buf = [], c, p = {}, cf, last = cs.length-1; - for(var i = 0, len = cs.length; i < len; i++){ - c = cs[i]; - cf = cfg[i]; - p.id = c.id; - p.style = c.style; - p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : ''); - if(cf.summaryType || cf.summaryRenderer){ - p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o); - }else{ - p.value = ''; - } - if(p.value == undefined || p.value === "") p.value = " "; - buf[buf.length] = this.cellTpl.apply(p); - } - - return this.rowTpl.apply({ - tstyle: 'width:'+this.view.getTotalWidth()+';', - cells: buf.join('') - }); - }, - - /** - * @private - * @param {Object} rs - * @param {Object} cs - */ - calculate : function(rs, cs){ - var data = {}, r, c, cfg = this.grid.getColumnModel().config, cf; - for(var j = 0, jlen = rs.length; j < jlen; j++){ - r = rs[j]; - for(var i = 0, len = cs.length; i < len; i++){ - c = cs[i]; - cf = cfg[i]; - if(cf.summaryType){ - data[c.name] = Ext.ux.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data); - } - } - } - return data; - }, - - doGroupEnd : function(buf, g, cs, ds, colCount){ - var data = this.calculate(g.rs, cs); - buf.push('', this.renderSummary({data: data}, cs), ''); - }, - - doWidth : function(col, w, tw){ - var gs = this.view.getGroups(), s; - for(var i = 0, len = gs.length; i < len; i++){ - s = gs[i].childNodes[2]; - s.style.width = tw; - s.firstChild.style.width = tw; - s.firstChild.rows[0].childNodes[col].style.width = w; - } - }, - - doAllWidths : function(ws, tw){ - var gs = this.view.getGroups(), s, cells, wlen = ws.length; - for(var i = 0, len = gs.length; i < len; i++){ - s = gs[i].childNodes[2]; - s.style.width = tw; - s.firstChild.style.width = tw; - cells = s.firstChild.rows[0].childNodes; - for(var j = 0; j < wlen; j++){ - cells[j].style.width = ws[j]; - } - } - }, - - doHidden : function(col, hidden, tw){ - var gs = this.view.getGroups(), s, display = hidden ? 'none' : ''; - for(var i = 0, len = gs.length; i < len; i++){ - s = gs[i].childNodes[2]; - s.style.width = tw; - s.firstChild.style.width = tw; - s.firstChild.rows[0].childNodes[col].style.display = display; - } - }, - - // Note: requires that all (or the first) record in the - // group share the same group value. Returns false if the group - // could not be found. - refreshSummary : function(groupValue){ - return this.refreshSummaryById(this.view.getGroupId(groupValue)); - }, - - getSummaryNode : function(gid){ - var g = Ext.fly(gid, '_gsummary'); - if(g){ - return g.down('.x-grid3-summary-row', true); - } - return null; - }, - - refreshSummaryById : function(gid){ - var g = Ext.getDom(gid); - if(!g){ - return false; - } - var rs = []; - this.grid.getStore().each(function(r){ - if(r._groupId == gid){ - rs[rs.length] = r; - } - }); - var cs = this.view.getColumnData(), - data = this.calculate(rs, cs), - markup = this.renderSummary({data: data}, cs), - existing = this.getSummaryNode(gid); - - if(existing){ - g.removeChild(existing); - } - Ext.DomHelper.append(g, markup); - return true; - }, - - doUpdate : function(ds, record){ - this.refreshSummaryById(record._groupId); - }, - - doRemove : function(ds, record, index, isUpdate){ - if(!isUpdate){ - this.refreshSummaryById(record._groupId); - } - }, - - /** - * Show a message in the summary row. - *

-grid.on('afteredit', function(){
-    var groupValue = 'Ext Forms: Field Anchoring';
-    summary.showSummaryMsg(groupValue, 'Updating Summary...');
-});
-     * 
- * @param {String} groupValue - * @param {String} msg Text to use as innerHTML for the summary row. - */ - showSummaryMsg : function(groupValue, msg){ - var gid = this.view.getGroupId(groupValue), - node = this.getSummaryNode(gid); - if(node){ - node.innerHTML = '
' + msg + '
'; - } - } -}); - -//backwards compat -Ext.grid.GroupSummary = Ext.ux.grid.GroupSummary; - - -/** - * Calculation types for summary row:

- *

Custom calculations may be implemented. An example of - * custom summaryType=totalCost:


-// define a custom summary function
-Ext.ux.grid.GroupSummary.Calculations['totalCost'] = function(v, record, field){
-    return v + (record.data.estimate * record.data.rate);
-};
- * 
- * @property Calculations - */ - -Ext.ux.grid.GroupSummary.Calculations = { - 'sum' : function(v, record, field){ - return v + (record.data[field]||0); - }, - - 'count' : function(v, record, field, data){ - return data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1); - }, - - 'max' : function(v, record, field, data){ - var v = record.data[field]; - var max = data[field+'max'] === undefined ? (data[field+'max'] = v) : data[field+'max']; - return v > max ? (data[field+'max'] = v) : max; - }, - - 'min' : function(v, record, field, data){ - var v = record.data[field]; - var min = data[field+'min'] === undefined ? (data[field+'min'] = v) : data[field+'min']; - return v < min ? (data[field+'min'] = v) : min; - }, - - 'average' : function(v, record, field, data){ - var c = data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1); - var t = (data[field+'total'] = ((data[field+'total']||0) + (record.data[field]||0))); - return t === 0 ? 0 : t / c; - } -}; -Ext.grid.GroupSummary.Calculations = Ext.ux.grid.GroupSummary.Calculations; - -/** - * @class Ext.ux.grid.HybridSummary - * @extends Ext.ux.grid.GroupSummary - * Adds capability to specify the summary data for the group via json as illustrated here: - *

-{
-    data: [
-        {
-            projectId: 100,     project: 'House',
-            taskId:    112, description: 'Paint',
-            estimate:    6,        rate:     150,
-            due:'06/24/2007'
-        },
-        ...
-    ],
-
-    summaryData: {
-        'House': {
-            description: 14, estimate: 9,
-                   rate: 99, due: new Date(2009, 6, 29),
-                   cost: 999
-        }
-    }
-}
- * 
- * - */ -Ext.ux.grid.HybridSummary = Ext.extend(Ext.ux.grid.GroupSummary, { - /** - * @private - * @param {Object} rs - * @param {Object} cs - */ - calculate : function(rs, cs){ - var gcol = this.view.getGroupField(), - gvalue = rs[0].data[gcol], - gdata = this.getSummaryData(gvalue); - return gdata || Ext.ux.grid.HybridSummary.superclass.calculate.call(this, rs, cs); - }, - - /** - *

-grid.on('afteredit', function(){
-    var groupValue = 'Ext Forms: Field Anchoring';
-    summary.showSummaryMsg(groupValue, 'Updating Summary...');
-    setTimeout(function(){ // simulate server call
-        // HybridSummary class implements updateSummaryData
-        summary.updateSummaryData(groupValue,
-            // create data object based on configured dataIndex
-            {description: 22, estimate: 888, rate: 888, due: new Date(), cost: 8});
-    }, 2000);
-});
-     * 
- * @param {String} groupValue - * @param {Object} data data object - * @param {Boolean} skipRefresh (Optional) Defaults to false - */ - updateSummaryData : function(groupValue, data, skipRefresh){ - var json = this.grid.getStore().reader.jsonData; - if(!json.summaryData){ - json.summaryData = {}; - } - json.summaryData[groupValue] = data; - if(!skipRefresh){ - this.refreshSummary(groupValue); - } - }, - - /** - * Returns the summaryData for the specified groupValue or null. - * @param {String} groupValue - * @return {Object} summaryData - */ - getSummaryData : function(groupValue){ - var json = this.grid.getStore().reader.jsonData; - if(json && json.summaryData){ - return json.summaryData[groupValue]; - } - return null; - } -}); - -//backwards compat -Ext.grid.HybridSummary = Ext.ux.grid.HybridSummary; +/*! + * Ext JS Library 3.2.0 + * Copyright(c) 2006-2010 Ext JS, Inc. + * licensing@extjs.com + * http://www.extjs.com/license + */ +Ext.ns('Ext.ux.grid'); + +/** + * @class Ext.ux.grid.GroupSummary + * @extends Ext.util.Observable + * A GridPanel plugin that enables dynamic column calculations and a dynamically + * updated grouped summary row. + */ +Ext.ux.grid.GroupSummary = Ext.extend(Ext.util.Observable, { + /** + * @cfg {Function} summaryRenderer Renderer example:

+summaryRenderer: function(v, params, data){
+    return ((v === 0 || v > 1) ? '(' + v +' Tasks)' : '(1 Task)');
+},
+     * 
+ */ + /** + * @cfg {String} summaryType (Optional) The type of + * calculation to be used for the column. For options available see + * {@link #Calculations}. + */ + + constructor : function(config){ + Ext.apply(this, config); + Ext.ux.grid.GroupSummary.superclass.constructor.call(this); + }, + init : function(grid){ + this.grid = grid; + var v = this.view = grid.getView(); + v.doGroupEnd = this.doGroupEnd.createDelegate(this); + + v.afterMethod('onColumnWidthUpdated', this.doWidth, this); + v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); + v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); + v.afterMethod('onUpdate', this.doUpdate, this); + v.afterMethod('onRemove', this.doRemove, this); + + if(!this.rowTpl){ + this.rowTpl = new Ext.Template( + '
', + '', + '{cells}', + '
' + ); + this.rowTpl.disableFormats = true; + } + this.rowTpl.compile(); + + if(!this.cellTpl){ + this.cellTpl = new Ext.Template( + '', + '
{value}
', + "" + ); + this.cellTpl.disableFormats = true; + } + this.cellTpl.compile(); + }, + + /** + * Toggle the display of the summary row on/off + * @param {Boolean} visible true to show the summary, false to hide the summary. + */ + toggleSummaries : function(visible){ + var el = this.grid.getGridEl(); + if(el){ + if(visible === undefined){ + visible = el.hasClass('x-grid-hide-summary'); + } + el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary'); + } + }, + + renderSummary : function(o, cs){ + cs = cs || this.view.getColumnData(); + var cfg = this.grid.getColumnModel().config, + buf = [], c, p = {}, cf, last = cs.length-1; + for(var i = 0, len = cs.length; i < len; i++){ + c = cs[i]; + cf = cfg[i]; + p.id = c.id; + p.style = c.style; + p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : ''); + if(cf.summaryType || cf.summaryRenderer){ + p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o); + }else{ + p.value = ''; + } + if(p.value == undefined || p.value === "") p.value = " "; + buf[buf.length] = this.cellTpl.apply(p); + } + + return this.rowTpl.apply({ + tstyle: 'width:'+this.view.getTotalWidth()+';', + cells: buf.join('') + }); + }, + + /** + * @private + * @param {Object} rs + * @param {Object} cs + */ + calculate : function(rs, cs){ + var data = {}, r, c, cfg = this.grid.getColumnModel().config, cf; + for(var j = 0, jlen = rs.length; j < jlen; j++){ + r = rs[j]; + for(var i = 0, len = cs.length; i < len; i++){ + c = cs[i]; + cf = cfg[i]; + if(cf.summaryType){ + data[c.name] = Ext.ux.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data); + } + } + } + return data; + }, + + doGroupEnd : function(buf, g, cs, ds, colCount){ + var data = this.calculate(g.rs, cs); + buf.push('', this.renderSummary({data: data}, cs), ''); + }, + + doWidth : function(col, w, tw){ + if(!this.isGrouped()){ + return; + } + var gs = this.view.getGroups(), + len = gs.length, + i = 0, + s; + for(; i < len; ++i){ + s = gs[i].childNodes[2]; + s.style.width = tw; + s.firstChild.style.width = tw; + s.firstChild.rows[0].childNodes[col].style.width = w; + } + }, + + doAllWidths : function(ws, tw){ + if(!this.isGrouped()){ + return; + } + var gs = this.view.getGroups(), + len = gs.length, + i = 0, + j, + s, + cells, + wlen = ws.length; + + for(; i < len; i++){ + s = gs[i].childNodes[2]; + s.style.width = tw; + s.firstChild.style.width = tw; + cells = s.firstChild.rows[0].childNodes; + for(j = 0; j < wlen; j++){ + cells[j].style.width = ws[j]; + } + } + }, + + doHidden : function(col, hidden, tw){ + if(!this.isGrouped()){ + return; + } + var gs = this.view.getGroups(), + len = gs.length, + i = 0, + s, + display = hidden ? 'none' : ''; + for(; i < len; i++){ + s = gs[i].childNodes[2]; + s.style.width = tw; + s.firstChild.style.width = tw; + s.firstChild.rows[0].childNodes[col].style.display = display; + } + }, + + isGrouped : function(){ + return !Ext.isEmpty(this.grid.getStore().groupField); + }, + + // Note: requires that all (or the first) record in the + // group share the same group value. Returns false if the group + // could not be found. + refreshSummary : function(groupValue){ + return this.refreshSummaryById(this.view.getGroupId(groupValue)); + }, + + getSummaryNode : function(gid){ + var g = Ext.fly(gid, '_gsummary'); + if(g){ + return g.down('.x-grid3-summary-row', true); + } + return null; + }, + + refreshSummaryById : function(gid){ + var g = Ext.getDom(gid); + if(!g){ + return false; + } + var rs = []; + this.grid.getStore().each(function(r){ + if(r._groupId == gid){ + rs[rs.length] = r; + } + }); + var cs = this.view.getColumnData(), + data = this.calculate(rs, cs), + markup = this.renderSummary({data: data}, cs), + existing = this.getSummaryNode(gid); + + if(existing){ + g.removeChild(existing); + } + Ext.DomHelper.append(g, markup); + return true; + }, + + doUpdate : function(ds, record){ + this.refreshSummaryById(record._groupId); + }, + + doRemove : function(ds, record, index, isUpdate){ + if(!isUpdate){ + this.refreshSummaryById(record._groupId); + } + }, + + /** + * Show a message in the summary row. + *

+grid.on('afteredit', function(){
+    var groupValue = 'Ext Forms: Field Anchoring';
+    summary.showSummaryMsg(groupValue, 'Updating Summary...');
+});
+     * 
+ * @param {String} groupValue + * @param {String} msg Text to use as innerHTML for the summary row. + */ + showSummaryMsg : function(groupValue, msg){ + var gid = this.view.getGroupId(groupValue), + node = this.getSummaryNode(gid); + if(node){ + node.innerHTML = '
' + msg + '
'; + } + } +}); + +//backwards compat +Ext.grid.GroupSummary = Ext.ux.grid.GroupSummary; + + +/** + * Calculation types for summary row:

+ *

Custom calculations may be implemented. An example of + * custom summaryType=totalCost:


+// define a custom summary function
+Ext.ux.grid.GroupSummary.Calculations['totalCost'] = function(v, record, field){
+    return v + (record.data.estimate * record.data.rate);
+};
+ * 
+ * @property Calculations + */ + +Ext.ux.grid.GroupSummary.Calculations = { + 'sum' : function(v, record, field){ + return v + (record.data[field]||0); + }, + + 'count' : function(v, record, field, data){ + return data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1); + }, + + 'max' : function(v, record, field, data){ + var v = record.data[field]; + var max = data[field+'max'] === undefined ? (data[field+'max'] = v) : data[field+'max']; + return v > max ? (data[field+'max'] = v) : max; + }, + + 'min' : function(v, record, field, data){ + var v = record.data[field]; + var min = data[field+'min'] === undefined ? (data[field+'min'] = v) : data[field+'min']; + return v < min ? (data[field+'min'] = v) : min; + }, + + 'average' : function(v, record, field, data){ + var c = data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1); + var t = (data[field+'total'] = ((data[field+'total']||0) + (record.data[field]||0))); + return t === 0 ? 0 : t / c; + } +}; +Ext.grid.GroupSummary.Calculations = Ext.ux.grid.GroupSummary.Calculations; + +/** + * @class Ext.ux.grid.HybridSummary + * @extends Ext.ux.grid.GroupSummary + * Adds capability to specify the summary data for the group via json as illustrated here: + *

+{
+    data: [
+        {
+            projectId: 100,     project: 'House',
+            taskId:    112, description: 'Paint',
+            estimate:    6,        rate:     150,
+            due:'06/24/2007'
+        },
+        ...
+    ],
+
+    summaryData: {
+        'House': {
+            description: 14, estimate: 9,
+                   rate: 99, due: new Date(2009, 6, 29),
+                   cost: 999
+        }
+    }
+}
+ * 
+ * + */ +Ext.ux.grid.HybridSummary = Ext.extend(Ext.ux.grid.GroupSummary, { + /** + * @private + * @param {Object} rs + * @param {Object} cs + */ + calculate : function(rs, cs){ + var gcol = this.view.getGroupField(), + gvalue = rs[0].data[gcol], + gdata = this.getSummaryData(gvalue); + return gdata || Ext.ux.grid.HybridSummary.superclass.calculate.call(this, rs, cs); + }, + + /** + *

+grid.on('afteredit', function(){
+    var groupValue = 'Ext Forms: Field Anchoring';
+    summary.showSummaryMsg(groupValue, 'Updating Summary...');
+    setTimeout(function(){ // simulate server call
+        // HybridSummary class implements updateSummaryData
+        summary.updateSummaryData(groupValue,
+            // create data object based on configured dataIndex
+            {description: 22, estimate: 888, rate: 888, due: new Date(), cost: 8});
+    }, 2000);
+});
+     * 
+ * @param {String} groupValue + * @param {Object} data data object + * @param {Boolean} skipRefresh (Optional) Defaults to false + */ + updateSummaryData : function(groupValue, data, skipRefresh){ + var json = this.grid.getStore().reader.jsonData; + if(!json.summaryData){ + json.summaryData = {}; + } + json.summaryData[groupValue] = data; + if(!skipRefresh){ + this.refreshSummary(groupValue); + } + }, + + /** + * Returns the summaryData for the specified groupValue or null. + * @param {String} groupValue + * @return {Object} summaryData + */ + getSummaryData : function(groupValue){ + var reader = this.grid.getStore().reader, + json = reader.jsonData, + fields = reader.recordType.prototype.fields, + v; + + if(json && json.summaryData){ + v = json.summaryData[groupValue]; + if(v){ + return reader.extractValues(v, fields.items, fields.length); + } + } + return null; + } +}); + +//backwards compat +Ext.grid.HybridSummary = Ext.ux.grid.HybridSummary;