GroupSummary.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:12k
源码类别:

中间件编程

开发平台:

JavaScript

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