/*jshint eqeqeq:false */ /*global jQuery, define */ (function( factory ) { "use strict"; if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. define([ "jquery", "./grid.base", "./grid.grouping" ], factory ); } else { // Browser globals factory( jQuery ); } }(function( $ ) { "use strict"; // To optimize the search we need custom array filter // This code is taken from // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter //module begin function _pivotfilter (fn, context) { /*jshint validthis: true */ var i, value, result = [], length; if (!this || typeof fn !== 'function' || (fn instanceof RegExp)) { throw new TypeError(); } length = this.length; for (i = 0; i < length; i++) { if (this.hasOwnProperty(i)) { value = this[i]; if (fn.call(context, value, i, this)) { result.push(value); // We need break in order to cancel loop // in case the row is found break; } } } return result; } $.assocArraySize = function(obj) { // http://stackoverflow.com/a/6700/11236 var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) { size++; } } return size; }; $.jgrid.extend({ pivotSetup : function( data, options ){ // data should come in json format // The function return the new colModel and the transformed data // again with group setup options which then will be passed to the grid var columns =[], pivotrows =[], summaries = [], member=[], labels=[], groupOptions = { grouping : true, groupingView : { groupField : [], groupSummary: [], groupSummaryPos:[] } }, headers = [], o = $.extend ( { rowTotals : false, rowTotalsText : 'Total', // summary columns colTotals : false, groupSummary : true, groupSummaryPos : 'header', frozenStaticCols : false }, options || {}); this.each(function(){ var row, rowindex, i, rowlen = data.length, xlen, ylen, aggrlen, tmp, newObj, r=0; // utility funcs /* * Filter the data to a given criteria. Return the firt occurance */ function find(ar, fun, extra) { var res; res = _pivotfilter.call(ar, fun, extra); return res.length > 0 ? res[0] : null; } /* * Check if the grouped row column exist (See find) * If the row is not find in pivot rows retun null, * otherviese the column */ function findGroup(item, index) { /*jshint validthis: true */ var j = 0, ret = true, i; for(i in item) { if( item.hasOwnProperty(i) ) { if(item[i] != this[j]) { ret = false; break; } j++; if(j>=this.length) { break; } } } if(ret) { rowindex = index; } return ret; } /* * Perform calculations of the pivot values. */ function calculation(oper, v, field, rc, _cnt) { var ret; switch (oper) { case "sum" : ret = parseFloat(v||0) + parseFloat((rc[field]||0)); break; case "count" : if(v==="" || v == null) { v=0; } if(rc.hasOwnProperty(field)) { ret = v+1; } else { ret = 0; } break; case "min" : if(v==="" || v == null) { ret = parseFloat(rc[field]||0); } else { ret =Math.min(parseFloat(v),parseFloat(rc[field]||0)); } break; case "max" : if(v==="" || v == null) { ret = parseFloat(rc[field]||0); } else { ret = Math.max(parseFloat(v),parseFloat(rc[field]||0)); } break; case "avg" : //avg grouping ret = (parseFloat(v||0) * (_cnt -1) + parseFloat(rc[field]||0) ) /_cnt; break; } return ret; } /* * The function agragates the values of the pivot grid. * Return the current row with pivot summary values */ function agregateFunc ( row, aggr, value, curr) { // default is sum var arrln = aggr.length, i, label, j, jv, mainval="",swapvals=[]; if($.isArray(value)) { jv = value.length; swapvals = value; } else { jv = 1; swapvals[0]=value; } member = []; labels = []; member.root = 0; if(! !!curr._count ){ curr._count = 1; }else{ curr._count ++; } for(j=0;j 0) { var dn = o.yDimension[0].dataName; o.yDimension.splice(0,0,{dataName:dn}); o.yDimension[0].converter = function(){ return '_r_Totals'; }; } // build initial columns (colModel) from xDimension xlen = $.isArray(o.xDimension) ? o.xDimension.length : 0; ylen = o.yDimension.length; aggrlen = $.isArray(o.aggregates) ? o.aggregates.length : 0; if(xlen === 0 || aggrlen === 0) { throw("xDimension or aggregates optiona are not set!"); } var colc; for(i = 0; i< xlen; i++) { colc = {name:o.xDimension[i].dataName, frozen: o.frozenStaticCols}; if(o.xDimension[i].isGroupField == null) { o.xDimension[i].isGroupField = true; } colc = $.extend(true, colc, o.xDimension[i]); columns.push( colc ); } var groupfields = xlen - 1, tree={}; //tree = { text: 'root', leaf: false, children: [] }; //loop over alll the source data while( r < rowlen ) { row = data[r]; var xValue = []; var yValue = []; tmp = {}; i = 0; // build the data from xDimension do { xValue[i] = $.trim(row[o.xDimension[i].dataName]); tmp[o.xDimension[i].dataName] = xValue[i]; i++; } while( i < xlen ); var k = 0; rowindex = -1; // check to see if the row is in our new pivotrow set newObj = find(pivotrows, findGroup, xValue); if(!newObj) { // if the row is not in our set k = 0; // if yDimension is set if(ylen>=1) { // build the cols set in yDimension for(k=0;k= 0) { k = 0; // make the recalculations if(ylen>=1) { for(k=0;k0) { headers[ylen-1] = { useColSpanStyle: false, groupHeaders: []}; } /* * Recursive function which uses the tree to build the * columns from the pivot values and set the group Headers */ function list(items) { var l, j, key, k, col; for (key in items) { // iterate if (items.hasOwnProperty(key)) { // write amount of spaces according to level // and write name and newline if(typeof items[key] !== "object") { // If not a object build the header of the appropriate level if( key === 'level') { if(lastval[items.level] === undefined) { lastval[items.level] =''; if(items.level>0 && items.text.indexOf('_r_Totals') === -1) { headers[items.level-1] = { useColSpanStyle: false, groupHeaders: [] }; } } if(lastval[items.level] !== items.text && items.children.length && items.text.indexOf('_r_Totals') === -1 ) { if(items.level>0) { headers[items.level-1].groupHeaders.push({ titleText: items.label, numberOfColumns : 0 }); var collen = headers[items.level-1].groupHeaders.length-1, colpos = collen === 0 ? swaplen : initColLen;//+aggrlen; if(items.level-1=== (o.rowTotals ? 1 : 0)) { if(collen>0) { var l1=0; for(var kk=0; kk0) { if( aggrlen > 1){ var ll=1; for( l in items.fields) { if(items.fields.hasOwnProperty(l)) { if(ll===1) { headers[ylen-1].groupHeaders.push({startColumnName: l, numberOfColumns: 1, titleText: items.label || items.text}); } ll++; } } headers[ylen-1].groupHeaders[headers[ylen-1].groupHeaders.length-1].numberOfColumns = ll-1; } else { headers.splice(ylen-1,1); } } } // if object, call recursively if (items[key] != null && typeof items[key] === "object") { list(items[key]); } // Finally build the columns if( key === 'level') { if( items.level > 0 && (items.level === (ylen===0?items.level:ylen) || lastval[items.level].indexOf('_r_Totals') !== -1 ) ){ j=0; for(l in items.fields) { if(items.fields.hasOwnProperty( l ) ) { col = {}; for(k in o.aggregates[j]) { if(o.aggregates[j].hasOwnProperty(k)) { switch( k ) { case 'member': case 'label': case 'aggregator': break; default: col[k] = o.aggregates[j][k]; } } } if(aggrlen > 1) { col.name = l; col.label = o.aggregates[j].label || items.label; } else { col.name = items.text; col.label = items.text==='_r_Totals' ? o.rowTotalsText : items.label; } columns.push (col); j++; } } } } } } } list( tree ); var nm; // loop again trougth the pivot rows in order to build grand total if(o.colTotals) { var plen = pivotrows.length; while(plen--) { for(i=xlen;i 0) { for(i=0;i 0 ? true : false, query= $.jgrid.from.call($t, pivotGrid.rows), i, so, st, len; if(pivotOpt.ignoreCase) { query = query.ignoreCase(); } for(i=0; i< pivotGrid.groupOptions.groupingView.groupField.length; i++) { so = pivotOpt.xDimension[i].sortorder ? pivotOpt.xDimension[i].sortorder : 'asc'; st = pivotOpt.xDimension[i].sorttype ? pivotOpt.xDimension[i].sorttype : 'text'; query.orderBy(pivotGrid.groupOptions.groupingView.groupField[i], so, st, '', st); } len = pivotOpt.xDimension.length; if(pivotGrid.groupOptions.sortname && len) { so = pivotOpt.xDimension[len-1].sortorder ? pivotOpt.xDimension[len-1].sortorder : 'asc'; st = pivotOpt.xDimension[len-1].sorttype ? pivotOpt.xDimension[len-1].sorttype : 'text'; query.orderBy(pivotGrid.groupOptions.sortname, so, st, '', st); } jQuery($t).jqGrid($.extend(true, { datastr: $.extend(query.select(),footerrow ? {userdata:pivotGrid.summary} : {}), datatype: "jsonstring", footerrow : footerrow, userDataOnFooter: footerrow, colModel: pivotGrid.colModel, viewrecords: true, sortname: pivotOpt.xDimension[0].dataName // ????? }, pivotGrid.groupOptions, gridOpt || {})); var gHead = pivotGrid.groupHeaders; if(gHead.length) { for( i = 0;i < gHead.length ; i++) { if(gHead[i] && gHead[i].groupHeaders.length) { jQuery($t).jqGrid('setGroupHeaders',gHead[i]); } } } if(pivotOpt.frozenStaticCols) { jQuery($t).jqGrid("setFrozenColumns"); } } if(typeof data === "string") { $.ajax($.extend({ url : data, dataType: 'json', success : function(response) { pivot($.jgrid.getAccessor(response, ajaxOpt && ajaxOpt.reader ? ajaxOpt.reader: 'rows') ); } }, ajaxOpt || {}) ); } else { pivot( data ); } }); } }); //module end }));