View Poll Results: Was this helpful?
- Voters
- 320. You may not vote on this poll
-
Yes - Very Much
247 77.19% -
Yes - Had to tweak it
43 13.44% -
No - Maybe
14 4.38% -
Not at All!!!
16 5.00%
Hybrid View
-
20 Dec 2007 1:42 AM #1
Grid Summary Plugin With Fixed Summary Row
Grid Summary Plugin With Fixed Summary Row
Code:[ hijacked by @mystix -- pardon me ;) ] for anyone who stumbles across this thread -- just fyi, the latest code can always be found in post #9. kudos still goes to @tinker for coming up with the initial code. --- mystix
Hi!
Some time back I found a "GroupSummary" plugin here and modified it to my need to have a table/grid level summary. I found another similar plugin here. but it does not seem to fix the summary row at the bottom. Since I had to fight a lot to get it working, thought just thought it my be helpful to make a post.
Code:Ext.grid.GridSummary = function(config){ Ext.apply(this, config); }; Ext.extend(Ext.grid.GridSummary, Ext.util.Observable, { init : function(grid){ this.grid = grid; this.cm = grid.getColumnModel(); this.view = grid.getView(); var v = this.view; v.layout = this.layout.createDelegate(this); v.afterMethod('refresh', this.refreshSummary, this); v.afterMethod('refreshRow', this.refreshSummary, this); v.afterMethod('onColumnWidthUpdated', this.doWidth, this); v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); v.afterMethod('onUpdate', this.refreshSummary, this); v.afterMethod('onRemove', this.refreshSummary, this); if(!this.rowTpl){ this.rowTpl = new Ext.Template( '<div class="x-grid3-summary-row" style="{tstyle}">', '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', '<tbody><tr>{cells}</tr></tbody>', '</table></div>' ); this.rowTpl.disableFormats = true; } this.rowTpl.compile(); if(!this.cellTpl){ this.cellTpl = new Ext.Template( '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}">', '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on">{value}</div>', "</td>" ); this.cellTpl.disableFormats = true; } this.cellTpl.compile(); }, renderSummary : function(o, cs){ cs = cs || this.view.getColumnData(); var cfg = this.cm.config; var 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('') }); }, calculate : function(rs, cs){ var data = {}, r, c, cfg = this.cm.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 && cf.summaryType){ data[c.name] = Ext.grid.GridSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data); } } } return data; }, layout : function(){ if (!this.view.summary) this.view.summary = Ext.DomHelper.insertAfter(this.view.mainBody.dom.parentNode, {tag:'div'}, true); if(!this.view.mainBody){ return; } var g = this.grid; var c = g.getGridEl(), cm = this.cm, expandCol = g.autoExpandColumn, gv = this.view; var csize = c.getSize(true); var vw = csize.width; if(!vw || !csize.height){ // display: none? return; } if(g.autoHeight){ this.view.scroller.dom.style.overflow = 'visible'; }else{ var smHeight = this.view.summary.getHeight(); var hdHeight = this.view.mainHd.getHeight(); this.view.el.setSize(csize.width, csize.height + smHeight); var vh = csize.height - (hdHeight) - (smHeight); this.view.scroller.setSize(vw, vh); this.view.innerHd.style.width = (vw)+'px'; } if(this.view.forceFit){ if(this.view.lastViewWidth != vw){ this.view.fitColumns(false, false); this.view.lastViewWidth = vw; } }else { this.view.autoExpand(); } this.view.onLayout(vw, vh); }, doWidth : function(col, w, tw){ var gs = this.view.getRows(), 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.getRows(), 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.getRows(), 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(){ var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows; var colCount = cm.getColumnCount(); if(ds.getCount() < 1){ return ""; } var cs = this.view.getColumnData(); var startRow = startRow || 0; var endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow; // records to render var rs = ds.getRange(); var buf = []; var data = this.calculate(rs, cs); buf.push('</div>', this.renderSummary({data: data}, cs), '</div>'); this.view.summary.update(buf.join('')); this.view.layout(); }, getSummaryNode : function(){ return this.view.summary }, showSummaryMsg : function(groupValue, msg){ var gid = this.view.getGroupId(groupValue); var node = this.getSummaryNode(gid); if(node){ node.innerHTML = '<div class="x-grid3-summary-msg">' + msg + '</div>'; } } }); Ext.grid.GridSummary.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.HybridGridSummary = Ext.extend(Ext.grid.GridSummary, { calculate : function(rs, cs){ var gcol = this.view.getGroupField(); var gvalue = rs[0].data[gcol]; var gdata = this.getSummaryData(gvalue); return gdata || Ext.grid.HybridGridSummary.superclass.calculate.call(this, rs, cs); }, updateSummaryData : function(groupValue, data, skipRefresh){ var json = this.grid.store.reader.jsonData; if(!json.summaryData){ json.summaryData = {}; } json.summaryData[groupValue] = data; if(!skipRefresh){ this.refreshSummary(groupValue); } }, getSummaryData : function(groupValue){ var json = this.grid.store.reader.jsonData; if(json && json.summaryData){ return json.summaryData[groupValue]; } return null; } });
-
21 Dec 2007 12:57 AM #2
It would be nice to have some screenshots attached? Or maybe a live example? Thanks.
"It is better to be young, pretty and rich instead old, ugly and poor."
(c) Alan Ford.
-
26 Dec 2007 5:09 PM #3
there's something wrong when you resize a column!
-
10 Jan 2008 10:48 AM #4
Examples for use would be nice too.
-
11 Jan 2008 8:19 AM #5
This looks and works almost perfectly thank you.
There are three problems and one feature that would make this summary perfect.- Resizing a header column does not change the positions of the summary row, this does work correctly in the other version that you acknowledge, however I much prefer the locked bottom position you have created.
- My summary information only seems to join numbers together for example 10,000 + 15,500 + 14,500 displays as 10,00015,50014,500 rather than 40,000 - this is most likely a stupid error or misunderstanding on my part but a pointer would be excellent. [Fixed this myself (my own stupid error) - should have set the data type for each xml column]
- When refreshing the contents of the grid the summary updates correctly using new information, however if the grid results are empty the summary shows the last set of summary information.
- New feature - Could the summary hidden/shown as a setting in JS so it could optionally be shown using a button event etc.
Again - great work.
MalcolmLast edited by mwh154; 14 Jan 2008 at 4:59 AM. Reason: First a question myself
-
14 Jan 2008 9:21 PM #6
Works great but I had to tweak the calculations in order for them to update properly
Code:Ext.grid.GridSummary.Calculations = { 'sum' : function(v, record, field){ //originally: return v + (record.data[field]||0); return parseFloat(v) + parseFloat(record.data[field]); }, '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))); //originally: t === 0 ? 0 : t / c; return t === 0 ? 0 : parseFloat(t) / parseFloat(c); } }
-
10 May 2008 9:59 PM #7
Thanks for your Grid Summary Plugin,that's very well
Thanks for your Grid Summary Plugin,that's very well
Thanks for your Grid Summary Plugin,that's very well!
But ,that's not my needed for my project,So,I'd changed it.
Now,your code that had modified by me can work to....
It's not Summary the grid data,the summary data is passed by my code.
that likes:
summary.setSumValue(Ext.decode("{'company':'Average','price':'1212.2','change':'1.23','pctChange':'123'}"));
the following is demo archive.
http://extjs.com/forum/attachment.ph...1&d=1210485284
thanks again!
ps: nice to communicate with me.
my QQ:67231242,Msn:longfeisoft@hotmail.com,Gtalk:longfeisoft@gtalk.com
(my English is not well,sorry!)
-
14 May 2008 3:18 PM #8
First off, thanks very much for this plugin! It works great!
This may be a stupid question, but is there an easy way to get the summary value it creates? (I want to use the value in a variable that I can post back to the server or use in calling another function).
-
14 May 2008 7:09 PM #9
@layne,
posts #31 - #36 should solve your problem.
Sencha Docs / Ext 3.x - ( Docs | Examples )
Learning Center / Saki's Examples (for 2.x) / HOWTO - ( Report Bugs | Post Proper Code )
-
16 May 2008 11:17 AM #10
thanks for you like it!
right,i think that i got a easy way to get the summary value .
when init the grid,the data need download by Store object, but my josn data that responsed from server is not only include the grid data,but also has the summary data.It likes that:
then,Your Store's proxy can add the following code:Code:{"rowcount":"2","items":[{"username":"longfei","salary":1000},":[{"username":"layne","salary":2000}],"summary":{"username":"total:","salary":3000}}
My English is not good,did you can see?Code:success:function(a,b){ var s = a.responseText; var j = Ext.decode(s); if(j&&j.summary) summary.setSumValue(j.suminfo); }Last edited by mystix; 26 May 2008 at 5:25 PM. Reason: use [code][/code] tags


Reply With Quote