View Poll Results: Was this helpful?

Voters
325. You may not vote on this poll
  • Yes - Very Much

    250 76.92%
  • Yes - Had to tweak it

    45 13.85%
  • No - Maybe

    14 4.31%
  • Not at All!!!

    16 4.92%
  1. #1
    Ext User tinker's Avatar
    Join Date
    Sep 2007
    Posts
    26
    Vote Rating
    1
    tinker is on a distinguished road

      1  

    Default 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;
        }
    });
    Attached Files

  2. #2
    Ext User violinista's Avatar
    Join Date
    Apr 2007
    Location
    Serbia
    Posts
    293
    Vote Rating
    0
    violinista is on a distinguished road

      0  

    Default


    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.

  3. #3
    Ext User
    Join Date
    Apr 2007
    Posts
    9
    Vote Rating
    0
    soreport is on a distinguished road

      0  

    Default


    there's something wrong when you resize a column!

  4. #4
    Ext JS Premium Member jared's Avatar
    Join Date
    Mar 2007
    Posts
    14
    Vote Rating
    0
    jared is on a distinguished road

      0  

    Default


    Examples for use would be nice too.

  5. #5
    Ext User
    Join Date
    Jan 2008
    Posts
    4
    Vote Rating
    0
    mwh154 is on a distinguished road

      0  

    Default


    This looks and works almost perfectly thank you.

    There are three problems and one feature that would make this summary perfect.
    1. 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.
    2. 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]
    3. 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.
    4. 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.

    Malcolm
    Last edited by mwh154; 14 Jan 2008 at 4:59 AM. Reason: First a question myself

  6. #6
    Ext User
    Join Date
    Jan 2008
    Posts
    3
    Vote Rating
    0
    JasonOng is on a distinguished road

      0  

    Default


    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);
        }
    }

  7. #7
    Ext User graveyardfashions's Avatar
    Join Date
    Dec 2007
    Posts
    78
    Vote Rating
    0
    graveyardfashions is on a distinguished road

      0  

    Question how do I use this? It sounds perfect!

    how do I use this? It sounds perfect!


    It sounds like this is exactly what I want! But I'm not sure how to implement it.

    Caveat: I'm a beginner, and I haven't been able to find an example of anyone using this within the forums.

    I added it as a plugin in the form:
    Code:
        var grid_TargetData_tab1 = new Ext.grid.GridPanel({
            ds: ds_TargetData_tab1,
            cm: tab1_colModel,
            height:'auto',
            width:950,
            anchor:'100% 100%',
            title:'Scores by Component',
            plugins: new Ext.grid.GridSummary(),
            stripeRows: 'true'
        });
    And I specified a summaryType in the columnModel (though I wasn't sure if I needed to use it as a renderer):
    Code:
    var tab1_colModel = new Ext.grid.ColumnModel([
            {id:'label', header: "PACE Components", width: 200, sortable: true, dataIndex: 'label'},
            {header: "Weight", width: 100, sortable: true, dataIndex: 'Weight', summaryType: 'sum'},
            {header: "Overall Score", width: 100, renderer: pctChange, sortable: true, dataIndex: 'Overall', summaryType: 'average'}, 
            {header: "Initial Call", width: 100, renderer: pctChange, sortable: true, dataIndex: 'call1', summaryType: 'average'}, 
            {header: "Secondary Call", width: 100, renderer: pctChange, sortable: true, dataIndex: 'call2', summaryType: 'average'},
    	{header: "NYC_NYJ Avg", width: 100, renderer: pctChange, sortable: true, dataIndex: 'group19', summaryType: 'average'},
    	{header: "East Avg", width: 100, renderer: pctChange, sortable: true, dataIndex: 'group17', summaryType: 'average'},
    	{header: "USA Avg", width: 100, renderer: pctChange, sortable: true, dataIndex: 'group15', summaryType: 'average'}
        ]);
    What else do I need to do? Heck, am I even correct up to this point? All I know is that I'm getting no Firebug errors, and no summary row.

    Thank you for any help you can give!

    Best wishes,
    Cat

  8. #8
    Ext User graveyardfashions's Avatar
    Join Date
    Dec 2007
    Posts
    78
    Vote Rating
    0
    graveyardfashions is on a distinguished road

      0  

    Default interesting!

    interesting!


    Ok, it seems my code above *is* making the summary line show up - IF I sort a column. When the page first loads, the summary row does not display. Once I sort a column, the grid re-renders and displays the summary row. I think I can work with the rendering to figure this out.

    Another thing I already figured out: unless I set a height on my grid, the summary row moves down within the tab as I sort the grid. It's hard to describe, but it is as if it floats further and further down the tab.

    So, tips for others:
    * be sure to have a defined height on your grid
    * if you don't see it at first, try sorting the grid or re-rendering it in some way
    * add math.round() to the average function

  9. #9
    Sencha - Community Support Team mystix's Avatar
    Join Date
    Mar 2007
    Location
    Singapore
    Posts
    6,236
    Vote Rating
    5
    mystix will become famous soon enough

      0  

    Default


    alritey, i needed to use this so i took the liberty of fixing the various bugs in this plugin.
    i made the following changes:
    • namespaced the plugin to Ext.ux.grid.GridSummary
    • removed the unused HybridGridSummary
    • added a drop-in example (adapted from array-grid.js in \examples\grid)
    • added css styles (taken from summary.css found in \examples\grid)
    • added synchronised scrolling for the GridSummary row
    • fixed various copy-paste bugs (from the GroupSummary plugin)
    • fixed other rendering bugs
    enjoy

    p.s. kudos to @tinker for an inspiring start


    Plugin js:
    Code:
    // see zip file
    Required css:
    Code:
    /* see zip file */
    [update 1]
    added toggleSummary() method

    [update 2]
    updated example


    [update 3]
    fixed bug in refreshSummary when no records are in the Store


    [update 4]
    • fixed toggleSummary bugs
    • updated example html (added more custom summary renderer examples)
    • overrode Ext.util.format.usMoney to fix $NaN.00 appearing in example when no Records exist


    [update 5]
    refresh GridSummary row when grid's store is updated


    [update 6]
    [update 7]
    fixed typo in calculate method


    [update 8]
    • added {attr} to cellTpl config (thanks to @lukas.wappler)
    • fixed 2 tiny closure bugs (i think ) in the calculate and renderSummary methods
    • added summary row tooltips to the included example


    [update 9]
    • fixed + refactored calculate method
    • added rowIndex to parameter list of methods in Ext.ux.grid.GridSummary.Calculations
    • refactored messy methods in Ext.ux.grid.GridSummary.Calculations
    • updated example


    [update 10]
    minor update -- scoped unintentional global variable "cells"

    [update 11]
    • updated included example to demonstrate Record insertion
    • minor code cleanup
    Attached Files
    Last edited by mystix; 2 Mar 2010 at 12:09 PM. Reason: update

  10. #10
    Ext User tinker's Avatar
    Join Date
    Sep 2007
    Posts
    26
    Vote Rating
    1
    tinker is on a distinguished road

      0  

    Smile thankx all!

    thankx all!


    hey all!

    thanks a lot for your responses... i have been away quite a long time and havnt been able to respond to any queries! sorry about that!

    i am happy that this post has helped and inspired many - have got more stuff in my mind that i wanna put here! and pretty soon!

    thanks!

Thread Participants: 132

  1. franklt69 (3 Posts)
  2. Condor (18 Posts)
  3. mapo (3 Posts)
  4. HarryC (1 Post)
  5. mystix (139 Posts)
  6. jared (1 Post)
  7. MaxT (1 Post)
  8. wayne_o (2 Posts)
  9. soreport (1 Post)
  10. violinista (1 Post)
  11. bloon (1 Post)
  12. Troy Wolf (1 Post)
  13. tobiu (1 Post)
  14. Deleter (3 Posts)
  15. sintax.era (2 Posts)
  16. chernomorez (1 Post)
  17. lychorojostone (2 Posts)
  18. 6epcepk (6 Posts)
  19. zaunaf (1 Post)
  20. SlashEMc2k (1 Post)
  21. americos (1 Post)
  22. Layne (1 Post)
  23. jamie.nicholson (1 Post)
  24. mscdex (1 Post)
  25. vnug (2 Posts)
  26. dima (3 Posts)
  27. froamer (3 Posts)
  28. mondomon (3 Posts)
  29. kenshin (1 Post)
  30. rtconner (2 Posts)
  31. juljupy (6 Posts)
  32. lukas.wappler (4 Posts)
  33. crpatrick (1 Post)
  34. saJoshua (7 Posts)
  35. crxtech (1 Post)
  36. vertigoMX (5 Posts)
  37. sayanb (3 Posts)
  38. graveyardfashions (2 Posts)
  39. mwh154 (1 Post)
  40. calavera (2 Posts)
  41. JasonOng (1 Post)
  42. httpdotcom (5 Posts)
  43. kimosabi (2 Posts)
  44. uygarpe (1 Post)
  45. csextjs (2 Posts)
  46. Richie1985 (7 Posts)
  47. eliezerreis (5 Posts)
  48. dado.cubo (1 Post)
  49. Rafael (16 Posts)
  50. chrissturm (2 Posts)
  51. thomasf (1 Post)
  52. Rainher (1 Post)
  53. timotti (2 Posts)
  54. hongfu (1 Post)
  55. rnfbr1 (2 Posts)
  56. issameddine (2 Posts)
  57. rums (4 Posts)
  58. nuser (6 Posts)
  59. mntek (2 Posts)
  60. MichaelOstrovsky (1 Post)
  61. anghuda (1 Post)
  62. longfeisoft (2 Posts)
  63. nameroc (1 Post)
  64. georgeblackjr (1 Post)
  65. vinnybozz (2 Posts)
  66. mcouillard (2 Posts)
  67. wwwtd (5 Posts)
  68. s4brown (2 Posts)
  69. Shmitt (12 Posts)
  70. CEBEP (1 Post)
  71. charleshimmer (7 Posts)
  72. ondra.cz (1 Post)
  73. Eisstern (3 Posts)
  74. rasto1968 (2 Posts)
  75. hpandey (1 Post)
  76. xpete (1 Post)
  77. pratapbm (1 Post)
  78. leonardb (2 Posts)
  79. Trinad (2 Posts)
  80. larkworm (1 Post)
  81. bobjbain (1 Post)
  82. NetFantom (1 Post)
  83. amini (2 Posts)
  84. quen567 (2 Posts)
  85. pieter333 (1 Post)
  86. creepi (1 Post)
  87. ekhanh101 (4 Posts)
  88. alexbanda1982 (1 Post)
  89. damon1977 (1 Post)
  90. pablosn (2 Posts)
  91. cnesbit (1 Post)
  92. uniring (2 Posts)
  93. Jim.Barrows (1 Post)
  94. y_joren3 (2 Posts)
  95. ranadheersingh (2 Posts)
  96. quicksilver_in (2 Posts)
  97. Bleak (1 Post)
  98. janasri (1 Post)
  99. agfk (4 Posts)
  100. mcaudle28 (3 Posts)
  101. msinn (2 Posts)
  102. madirishman (2 Posts)
  103. blackghost (6 Posts)
  104. zvds (1 Post)
  105. sonixbp (5 Posts)
  106. tripEXITo (1 Post)
  107. erikenge (1 Post)
  108. sideview1 (1 Post)
  109. kuthz (1 Post)
  110. AfzalA (1 Post)
  111. pomuchi (1 Post)
  112. DerSalz (2 Posts)
  113. brycekmartin (2 Posts)
  114. malkandari (1 Post)
  115. eurobax (3 Posts)
  116. Fallen Zen (6 Posts)
  117. mayurid (1 Post)
  118. rOCTb (1 Post)
  119. t2nguyen (1 Post)
  120. Manivel (10 Posts)
  121. wigwam_salesman (13 Posts)
  122. ExTriqui (4 Posts)
  123. Tod (2 Posts)
  124. PavelG (1 Post)
  125. joelchu (1 Post)
  126. optiplex (1 Post)
  127. grace.lawrence (1 Post)
  128. bhuskey (2 Posts)
  129. jimprotos (1 Post)
  130. anuruddha84 (1 Post)
  131. Mcaveti (1 Post)
  132. arunmatics (1 Post)
Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..."