--- /dev/null
+<html>\r
+<head>\r
+ <title>The source code</title>\r
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
+</head>\r
+<body onload="prettyPrint();">\r
+ <pre class="prettyprint lang-js">Ext.ns('Ext.ux.grid');\r
+\r
+<div id="cls-Ext.ux.grid.GroupSummary"></div>/**\r
+ * @class Ext.ux.grid.GroupSummary\r
+ * @extends Ext.util.Observable\r
+ * A GridPanel plugin that enables dynamic column calculations and a dynamically\r
+ * updated grouped summary row.\r
+ */\r
+Ext.ux.grid.GroupSummary = Ext.extend(Ext.util.Observable, {\r
+ <div id="cfg-Ext.ux.grid.GroupSummary-summaryRenderer"></div>/**\r
+ * @cfg {Function} summaryRenderer Renderer example:<pre><code>\r
+summaryRenderer: function(v, params, data){\r
+ return ((v === 0 || v > 1) ? '(' + v +' Tasks)' : '(1 Task)');\r
+},\r
+ * </code></pre>\r
+ */\r
+ <div id="cfg-Ext.ux.grid.GroupSummary-summaryType"></div>/**\r
+ * @cfg {String} summaryType (Optional) The type of\r
+ * calculation to be used for the column. For options available see\r
+ * {@link #Calculations}.\r
+ */\r
+\r
+ constructor : function(config){\r
+ Ext.apply(this, config);\r
+ Ext.ux.grid.GroupSummary.superclass.constructor.call(this);\r
+ },\r
+ init : function(grid){\r
+ this.grid = grid;\r
+ this.cm = grid.getColumnModel();\r
+ this.view = grid.getView();\r
+\r
+ var v = this.view;\r
+ v.doGroupEnd = this.doGroupEnd.createDelegate(this);\r
+\r
+ v.afterMethod('onColumnWidthUpdated', this.doWidth, this);\r
+ v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);\r
+ v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);\r
+ v.afterMethod('onUpdate', this.doUpdate, this);\r
+ v.afterMethod('onRemove', this.doRemove, this);\r
+\r
+ if(!this.rowTpl){\r
+ this.rowTpl = new Ext.Template(\r
+ '<div class="x-grid3-summary-row" style="{tstyle}">',\r
+ '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
+ '<tbody><tr>{cells}</tr></tbody>',\r
+ '</table></div>'\r
+ );\r
+ this.rowTpl.disableFormats = true;\r
+ }\r
+ this.rowTpl.compile();\r
+\r
+ if(!this.cellTpl){\r
+ this.cellTpl = new Ext.Template(\r
+ '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',\r
+ '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on">{value}</div>',\r
+ "</td>"\r
+ );\r
+ this.cellTpl.disableFormats = true;\r
+ }\r
+ this.cellTpl.compile();\r
+ },\r
+\r
+ <div id="method-Ext.ux.grid.GroupSummary-toggleSummaries"></div>/**\r
+ * Toggle the display of the summary row on/off\r
+ * @param {Boolean} visible <tt>true</tt> to show the summary, <tt>false</tt> to hide the summary.\r
+ */\r
+ toggleSummaries : function(visible){\r
+ var el = this.grid.getGridEl();\r
+ if(el){\r
+ if(visible === undefined){\r
+ visible = el.hasClass('x-grid-hide-summary');\r
+ }\r
+ el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');\r
+ }\r
+ },\r
+\r
+ renderSummary : function(o, cs){\r
+ cs = cs || this.view.getColumnData();\r
+ var cfg = this.cm.config;\r
+\r
+ var buf = [], c, p = {}, cf, last = cs.length-1;\r
+ for(var i = 0, len = cs.length; i < len; i++){\r
+ c = cs[i];\r
+ cf = cfg[i];\r
+ p.id = c.id;\r
+ p.style = c.style;\r
+ p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
+ if(cf.summaryType || cf.summaryRenderer){\r
+ p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o);\r
+ }else{\r
+ p.value = '';\r
+ }\r
+ if(p.value == undefined || p.value === "") p.value = " ";\r
+ buf[buf.length] = this.cellTpl.apply(p);\r
+ }\r
+\r
+ return this.rowTpl.apply({\r
+ tstyle: 'width:'+this.view.getTotalWidth()+';',\r
+ cells: buf.join('')\r
+ });\r
+ },\r
+\r
+ /**\r
+ * @private\r
+ * @param {Object} rs\r
+ * @param {Object} cs\r
+ */\r
+ calculate : function(rs, cs){\r
+ var data = {}, r, c, cfg = this.cm.config, cf;\r
+ for(var j = 0, jlen = rs.length; j < jlen; j++){\r
+ r = rs[j];\r
+ for(var i = 0, len = cs.length; i < len; i++){\r
+ c = cs[i];\r
+ cf = cfg[i];\r
+ if(cf.summaryType){\r
+ data[c.name] = Ext.ux.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data);\r
+ }\r
+ }\r
+ }\r
+ return data;\r
+ },\r
+\r
+ doGroupEnd : function(buf, g, cs, ds, colCount){\r
+ var data = this.calculate(g.rs, cs);\r
+ buf.push('</div>', this.renderSummary({data: data}, cs), '</div>');\r
+ },\r
+\r
+ doWidth : function(col, w, tw){\r
+ var gs = this.view.getGroups(), s;\r
+ for(var i = 0, len = gs.length; i < len; i++){\r
+ s = gs[i].childNodes[2];\r
+ s.style.width = tw;\r
+ s.firstChild.style.width = tw;\r
+ s.firstChild.rows[0].childNodes[col].style.width = w;\r
+ }\r
+ },\r
+\r
+ doAllWidths : function(ws, tw){\r
+ var gs = this.view.getGroups(), s, cells, wlen = ws.length;\r
+ for(var i = 0, len = gs.length; i < len; i++){\r
+ s = gs[i].childNodes[2];\r
+ s.style.width = tw;\r
+ s.firstChild.style.width = tw;\r
+ cells = s.firstChild.rows[0].childNodes;\r
+ for(var j = 0; j < wlen; j++){\r
+ cells[j].style.width = ws[j];\r
+ }\r
+ }\r
+ },\r
+\r
+ doHidden : function(col, hidden, tw){\r
+ var gs = this.view.getGroups(), s, display = hidden ? 'none' : '';\r
+ for(var i = 0, len = gs.length; i < len; i++){\r
+ s = gs[i].childNodes[2];\r
+ s.style.width = tw;\r
+ s.firstChild.style.width = tw;\r
+ s.firstChild.rows[0].childNodes[col].style.display = display;\r
+ }\r
+ },\r
+\r
+ // Note: requires that all (or the first) record in the\r
+ // group share the same group value. Returns false if the group\r
+ // could not be found.\r
+ refreshSummary : function(groupValue){\r
+ return this.refreshSummaryById(this.view.getGroupId(groupValue));\r
+ },\r
+\r
+ getSummaryNode : function(gid){\r
+ var g = Ext.fly(gid, '_gsummary');\r
+ if(g){\r
+ return g.down('.x-grid3-summary-row', true);\r
+ }\r
+ return null;\r
+ },\r
+\r
+ refreshSummaryById : function(gid){\r
+ var g = document.getElementById(gid);\r
+ if(!g){\r
+ return false;\r
+ }\r
+ var rs = [];\r
+ this.grid.store.each(function(r){\r
+ if(r._groupId == gid){\r
+ rs[rs.length] = r;\r
+ }\r
+ });\r
+ var cs = this.view.getColumnData();\r
+ var data = this.calculate(rs, cs);\r
+ var markup = this.renderSummary({data: data}, cs);\r
+\r
+ var existing = this.getSummaryNode(gid);\r
+ if(existing){\r
+ g.removeChild(existing);\r
+ }\r
+ Ext.DomHelper.append(g, markup);\r
+ return true;\r
+ },\r
+\r
+ doUpdate : function(ds, record){\r
+ this.refreshSummaryById(record._groupId);\r
+ },\r
+\r
+ doRemove : function(ds, record, index, isUpdate){\r
+ if(!isUpdate){\r
+ this.refreshSummaryById(record._groupId);\r
+ }\r
+ },\r
+\r
+ <div id="method-Ext.ux.grid.GroupSummary-showSummaryMsg"></div>/**\r
+ * Show a message in the summary row.\r
+ * <pre><code>\r
+grid.on('afteredit', function(){\r
+ var groupValue = 'Ext Forms: Field Anchoring';\r
+ summary.showSummaryMsg(groupValue, 'Updating Summary...');\r
+});\r
+ * </code></pre>\r
+ * @param {String} groupValue\r
+ * @param {String} msg Text to use as innerHTML for the summary row.\r
+ */\r
+ showSummaryMsg : function(groupValue, msg){\r
+ var gid = this.view.getGroupId(groupValue);\r
+ var node = this.getSummaryNode(gid);\r
+ if(node){\r
+ node.innerHTML = '<div class="x-grid3-summary-msg">' + msg + '</div>';\r
+ }\r
+ }\r
+});\r
+\r
+//backwards compat\r
+Ext.grid.GroupSummary = Ext.ux.grid.GroupSummary;\r
+\r
+\r
+<div id="prop-Ext.ux.grid.GroupSummary-Calculations"></div>/**\r
+ * Calculation types for summary row:</p><div class="mdetail-params"><ul>\r
+ * <li><b><tt>sum</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>count</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>max</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>min</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>average</tt></b> : <div class="sub-desc"></div></li>\r
+ * </ul></div>\r
+ * <p>Custom calculations may be implemented. An example of\r
+ * custom <code>summaryType=totalCost</code>:</p><pre><code>\r
+// define a custom summary function\r
+Ext.ux.grid.GroupSummary.Calculations['totalCost'] = function(v, record, field){\r
+ return v + (record.data.estimate * record.data.rate);\r
+};\r
+ * </code></pre>\r
+ * @property Calculations\r
+ */\r
+\r
+Ext.ux.grid.GroupSummary.Calculations = {\r
+ 'sum' : function(v, record, field){\r
+ return v + (record.data[field]||0);\r
+ },\r
+\r
+ 'count' : function(v, record, field, data){\r
+ return data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);\r
+ },\r
+\r
+ 'max' : function(v, record, field, data){\r
+ var v = record.data[field];\r
+ var max = data[field+'max'] === undefined ? (data[field+'max'] = v) : data[field+'max'];\r
+ return v > max ? (data[field+'max'] = v) : max;\r
+ },\r
+\r
+ 'min' : function(v, record, field, data){\r
+ var v = record.data[field];\r
+ var min = data[field+'min'] === undefined ? (data[field+'min'] = v) : data[field+'min'];\r
+ return v < min ? (data[field+'min'] = v) : min;\r
+ },\r
+\r
+ 'average' : function(v, record, field, data){\r
+ var c = data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);\r
+ var t = (data[field+'total'] = ((data[field+'total']||0) + (record.data[field]||0)));\r
+ return t === 0 ? 0 : t / c;\r
+ }\r
+};\r
+Ext.grid.GroupSummary.Calculations = Ext.ux.grid.GroupSummary.Calculations;\r
+\r
+<div id="cls-Ext.ux.grid.HybridSummary"></div>/**\r
+ * @class Ext.ux.grid.HybridSummary\r
+ * @extends Ext.ux.grid.GroupSummary\r
+ * Adds capability to specify the summary data for the group via json as illustrated here:\r
+ * <pre><code>\r
+{\r
+ data: [\r
+ {\r
+ projectId: 100, project: 'House',\r
+ taskId: 112, description: 'Paint',\r
+ estimate: 6, rate: 150,\r
+ due:'06/24/2007'\r
+ },\r
+ ...\r
+ ],\r
+\r
+ summaryData: {\r
+ 'House': {\r
+ description: 14, estimate: 9,\r
+ rate: 99, due: new Date(2009, 6, 29),\r
+ cost: 999\r
+ }\r
+ }\r
+}\r
+ * </code></pre>\r
+ *\r
+ */\r
+Ext.ux.grid.HybridSummary = Ext.extend(Ext.ux.grid.GroupSummary, {\r
+ /**\r
+ * @private\r
+ * @param {Object} rs\r
+ * @param {Object} cs\r
+ */\r
+ calculate : function(rs, cs){\r
+ var gcol = this.view.getGroupField();\r
+ var gvalue = rs[0].data[gcol];\r
+ var gdata = this.getSummaryData(gvalue);\r
+ return gdata || Ext.ux.grid.HybridSummary.superclass.calculate.call(this, rs, cs);\r
+ },\r
+\r
+ <div id="method-Ext.ux.grid.HybridSummary-updateSummaryData"></div>/**\r
+ * <pre><code>\r
+grid.on('afteredit', function(){\r
+ var groupValue = 'Ext Forms: Field Anchoring';\r
+ summary.showSummaryMsg(groupValue, 'Updating Summary...');\r
+ setTimeout(function(){ // simulate server call\r
+ // HybridSummary class implements updateSummaryData\r
+ summary.updateSummaryData(groupValue,\r
+ // create data object based on configured dataIndex\r
+ {description: 22, estimate: 888, rate: 888, due: new Date(), cost: 8});\r
+ }, 2000);\r
+});\r
+ * </code></pre>\r
+ * @param {String} groupValue\r
+ * @param {Object} data data object\r
+ * @param {Boolean} skipRefresh (Optional) Defaults to false\r
+ */\r
+ updateSummaryData : function(groupValue, data, skipRefresh){\r
+ var json = this.grid.store.reader.jsonData;\r
+ if(!json.summaryData){\r
+ json.summaryData = {};\r
+ }\r
+ json.summaryData[groupValue] = data;\r
+ if(!skipRefresh){\r
+ this.refreshSummary(groupValue);\r
+ }\r
+ },\r
+\r
+ <div id="method-Ext.ux.grid.HybridSummary-getSummaryData"></div>/**\r
+ * Returns the summaryData for the specified groupValue or null.\r
+ * @param {String} groupValue\r
+ * @return {Object} summaryData\r
+ */\r
+ getSummaryData : function(groupValue){\r
+ var json = this.grid.store.reader.jsonData;\r
+ if(json && json.summaryData){\r
+ return json.summaryData[groupValue];\r
+ }\r
+ return null;\r
+ }\r
+});\r
+\r
+//backwards compat\r
+Ext.grid.HybridSummary = Ext.ux.grid.HybridSummary;\r
+</pre> \r
+</body>\r
+</html>
\ No newline at end of file