1 var ColumnCalcs =
function(table){
5 this.genColumn =
false;
6 this.topElement = this.createElement();
7 this.botElement = this.createElement();
10 this.topInitialized =
false;
11 this.botInitialized =
false;
16 ColumnCalcs.prototype.createElement =
function (){
17 var el = document.createElement(
"div");
18 el.classList.add(
"tabulator-calcs-holder");
22 ColumnCalcs.prototype.initialize =
function(){
23 this.genColumn =
new Column({field:
"value"},
this);
27 ColumnCalcs.prototype.registerColumnField =
function(){};
30 ColumnCalcs.prototype.initializeColumn =
function(column){
31 var def = column.definition
34 topCalcParams:def.topCalcParams || {},
35 botCalcParams:def.bottomCalcParams || {},
40 switch(typeof def.topCalc){
42 if(this.calculations[def.topCalc]){
43 config.topCalc = this.calculations[def.topCalc]
45 console.warn(
"Column Calc Error - No such calculation found, ignoring: ", def.topCalc);
50 config.topCalc = def.topCalc;
56 column.modules.columnCalcs = config;
57 this.topCalcs.push(column);
59 if(this.table.options.columnCalcs !=
"group"){
60 this.initializeTopRow();
67 switch(typeof def.bottomCalc){
69 if(this.calculations[def.bottomCalc]){
70 config.botCalc = this.calculations[def.bottomCalc]
72 console.warn(
"Column Calc Error - No such calculation found, ignoring: ", def.bottomCalc);
77 config.botCalc = def.bottomCalc;
83 column.modules.columnCalcs = config;
84 this.botCalcs.push(column);
86 if(this.table.options.columnCalcs !=
"group"){
87 this.initializeBottomRow();
94 ColumnCalcs.prototype.removeCalcs =
function(){
97 if(this.topInitialized){
98 this.topInitialized =
false;
99 this.topElement.parentNode.removeChild(this.topElement);
103 if(this.botInitialized){
104 this.botInitialized =
false;
105 this.table.footerManager.remove(this.botElement);
110 this.table.rowManager.adjustTableSize();
114 ColumnCalcs.prototype.initializeTopRow =
function(){
115 if(!this.topInitialized){
117 this.table.columnManager.getElement().insertBefore(this.topElement, this.table.columnManager.headersElement.nextSibling);
118 this.topInitialized =
true;
122 ColumnCalcs.prototype.initializeBottomRow =
function(){
123 if(!this.botInitialized){
124 this.table.footerManager.prepend(this.botElement);
125 this.botInitialized =
true;
130 ColumnCalcs.prototype.scrollHorizontal =
function(left){
132 scrollWidth = this.table.columnManager.getElement().scrollWidth - this.table.element.clientWidth;
134 if(this.botInitialized){
135 this.botRow.getElement().style.marginLeft = (-left) +
"px";
140 ColumnCalcs.prototype.recalc =
function(rows){
143 if(this.topInitialized || this.botInitialized){
144 data = this.rowsToData(rows);
146 if(this.topInitialized){
148 this.topRow.deleteCells();
151 row = this.generateRow(
"top", this.rowsToData(rows))
153 while(this.topElement.firstChild) this.topElement.removeChild(this.topElement.firstChild);
154 this.topElement.appendChild(row.getElement());
155 row.initialize(true);
158 if(this.botInitialized){
160 this.botRow.deleteCells();
163 row = this.generateRow(
"bottom", this.rowsToData(rows))
165 while(this.botElement.firstChild) this.botElement.removeChild(this.botElement.firstChild);
166 this.botElement.appendChild(row.getElement());
167 row.initialize(true);
170 this.table.rowManager.adjustTableSize();
173 if(this.table.modExists("frozenColumns")){
174 this.table.modules.frozenColumns.layout();
179 ColumnCalcs.prototype.recalcRowGroup =
function(row){
180 this.recalcGroup(this.table.modules.groupRows.getRowGroup(row));
183 ColumnCalcs.prototype.recalcGroup =
function(group){
188 if(group.calcs.bottom){
189 data = this.rowsToData(group.rows);
190 rowData = this.generateRowData(
"bottom", data);
192 group.calcs.bottom.updateData(rowData);
193 group.calcs.bottom.reinitialize();
197 data = this.rowsToData(group.rows);
198 rowData = this.generateRowData(
"top", data);
200 group.calcs.top.updateData(rowData);
201 group.calcs.top.reinitialize();
210 ColumnCalcs.prototype.generateTopRow =
function(rows){
211 return this.generateRow(
"top", this.rowsToData(rows));
214 ColumnCalcs.prototype.generateBottomRow =
function(rows){
215 return this.generateRow(
"bottom", this.rowsToData(rows));
218 ColumnCalcs.prototype.rowsToData =
function(rows){
221 rows.forEach(
function(row){
222 data.push(row.getData());
229 ColumnCalcs.prototype.generateRow =
function(pos, data){
231 rowData = this.generateRowData(pos, data),
234 if(
self.table.modExists(
"mutator")){
235 self.table.modules.mutator.disable();
238 row =
new Row(rowData,
this,
"calc");
240 if(
self.table.modExists(
"mutator")){
241 self.table.modules.mutator.enable();
244 row.getElement().classList.add(
"tabulator-calcs",
"tabulator-calcs-" + pos);
246 row.generateCells =
function(){
250 self.table.columnManager.columnsByIndex.forEach(
function(column){
253 self.genColumn.setField(column.getField());
254 self.genColumn.hozAlign = column.hozAlign;
256 if(column.definition[pos +
"CalcFormatter"] &&
self.table.modExists(
"format")){
258 self.genColumn.modules.format = {
259 formatter:
self.table.modules.format.getFormatter(column.definition[pos +
"CalcFormatter"]),
260 params: column.definition[pos +
"CalcFormatterParams"]
263 self.genColumn.modules.format = {
264 formatter:
self.table.modules.format.getFormatter(
"plaintext"),
270 self.genColumn.definition.cssClass = column.definition.cssClass;
273 var cell =
new Cell(
self.genColumn, row);
274 cell.column = column;
277 column.cells.push(cell);
292 ColumnCalcs.prototype.generateRowData =
function(pos, data){
294 calcs = pos ==
"top" ? this.topCalcs : this.botCalcs,
295 type = pos ==
"top" ?
"topCalc" :
"botCalc",
298 calcs.forEach(
function(column){
301 if(column.modules.columnCalcs && column.modules.columnCalcs[type]){
302 data.forEach(
function(item){
303 values.push(column.getFieldValue(item));
306 paramKey = type +
"Params";
307 params = typeof column.modules.columnCalcs[paramKey] ===
"function" ? column.modules.columnCalcs[paramKey](values, data) : column.modules.columnCalcs[paramKey];
309 column.setFieldValue(rowData, column.modules.columnCalcs[type](values, data, params));
316 ColumnCalcs.prototype.hasTopCalcs =
function(){
317 return !!(this.topCalcs.length);
320 ColumnCalcs.prototype.hasBottomCalcs =
function(){
321 return !!(this.botCalcs.length);
325 ColumnCalcs.prototype.redraw =
function(){
327 this.topRow.normalizeHeight(
true);
330 this.botRow.normalizeHeight(
true);
335 ColumnCalcs.prototype.getResults =
function(){
340 if(this.table.options.groupBy &&
this.table.modExists(
"groupRows")){
341 groups = this.table.modules.groupRows.getGroups(
true);
343 groups.forEach(
function(group){
344 results[group.getKey()] =
self.getGroupResults(group);
348 top: this.topRow ? this.topRow.getData() : {},
349 bottom: this.botRow ? this.botRow.getData() : {},
357 ColumnCalcs.prototype.getGroupResults =
function(group){
359 groupObj = group._getSelf(),
360 subGroups = group.getSubGroups(),
361 subGroupResults = {},
364 subGroups.forEach(
function(subgroup){
365 subGroupResults[subgroup.getKey()] =
self.getGroupResults(subgroup);
369 top: groupObj.calcs.top ? groupObj.calcs.top.getData() : {},
370 bottom: groupObj.calcs.bottom ? groupObj.calcs.bottom.getData() : {},
371 groups: subGroupResults,
379 ColumnCalcs.prototype.calculations = {
380 "avg":
function(values, data, calcParams){
382 precision = typeof calcParams.precision !==
"undefined" ? calcParams.precision : 2
385 output = values.reduce(
function(sum, value){
386 value = Number(value);
390 output = output / values.length;
392 output = precision !==
false ? output.toFixed(precision) : output;
395 return parseFloat(output).toString();
397 "max":
function(values, data, calcParams){
399 precision = typeof calcParams.precision !==
"undefined" ? calcParams.precision :
false;
401 values.forEach(
function(value){
403 value = Number(value);
405 if(value > output || output === null){
410 return output !== null ? (precision !==
false ? output.toFixed(precision) : output) :
"";
412 "min":
function(values, data, calcParams){
414 precision = typeof calcParams.precision !==
"undefined" ? calcParams.precision :
false;
416 values.forEach(
function(value){
418 value = Number(value);
420 if(value < output || output === null){
425 return output !== null ? (precision !==
false ? output.toFixed(precision) : output) :
"";
427 "sum":
function(values, data, calcParams){
429 precision = typeof calcParams.precision !==
"undefined" ? calcParams.precision :
false;
432 values.forEach(
function(value){
433 value = Number(value);
435 output += !isNaN(value) ? Number(value) : 0;
439 return precision !==
false ? output.toFixed(precision) : output;
441 "concat":
function(values, data, calcParams){
445 output = values.reduce(
function(sum, value){
446 return String(sum) + String(value);
452 "count":
function(values, data, calcParams){
456 values.forEach(
function(value){
469 Tabulator.prototype.registerModule(
"columnCalcs", ColumnCalcs);