1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-06-01 05:23:02 +02:00

Merge pull request #389 from koalyptus/332-colops-refactor

332 colops refactor
This commit is contained in:
koalyptus 2017-01-15 17:49:08 +11:00 committed by GitHub
commit 47d350470c
21 changed files with 419 additions and 309 deletions

View file

@ -11,8 +11,8 @@
"array-bracket-spacing": 2,
"keyword-spacing": ["error", { "after": true, "before": true }],
"max-depth": [2, 7],
"max-statements": [2, 150],
"complexity": [2, 83],
"max-statements": [2, 144],
"complexity": [2, 78],
"no-unused-vars": 2,
"no-eval": 2,
"no-underscore-dangle": 0,

4
dist/starter.html vendored
View file

@ -1,10 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>tablefilter v0.4.33 - Starter</title>
<title>tablefilter v0.4.34 - Starter</title>
</head>
<body>
<h1>tablefilter v0.4.33</h1>
<h1>tablefilter v0.4.34</h1>

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
span.colVisSpan{text-align:left;}span.colVisSpan a.colVis{display:inline-block;padding:7px 5px 0;font-size:inherit;font-weight:inherit;vertical-align:top}div.colVisCont{position:relative;background:#fff;-webkit-box-shadow:3px 3px 2px #888;-moz-box-shadow:3px 3px 2px #888;box-shadow:3px 3px 2px #888;position:absolute;display:none;border:1px solid #ccc;height:auto;width:250px;background-color:#fff;margin:35px 0 0 -100px;z-index:10000;padding:10px 10px 10px 10px;text-align:left;font-size:12px;}div.colVisCont:after,div.colVisCont:before{bottom:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.colVisCont:after{border-color:rgba(255,255,255,0);border-bottom-color:#fff;border-width:10px;margin-left:-10px}div.colVisCont:before{border-color:rgba(255,255,255,0);border-bottom-color:#ccc;border-width:12px;margin-left:-12px}div.colVisCont p{margin:6px auto 6px auto}div.colVisCont a.colVis{display:initial;font-weight:inherit}ul.cols_checklist{padding:0;margin:0;list-style:none;}ul.cols_checklist label{display:block}ul.cols_checklist input{vertical-align:middle;margin:2px 5px 2px 1px}li.cols_checklist_item{padding:4px;margin:0;}li.cols_checklist_item:hover{background-color:#335ea8;color:#fff}.cols_checklist_slc_item{background-color:#335ea8;color:#fff}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
span.expClpFlt a.btnExpClpFlt{width:35px;height:35px;display:inline-block;}span.expClpFlt a.btnExpClpFlt:hover{background-color:#f4f4f4}span.expClpFlt img{padding:8px 11px 11px 11px}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
.activeHeader{background-color:#66afe9 !important;color:#fff !important}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
table.TF{border-left:1px solid #ccc;border-top:none;border-right:none;border-bottom:none;}table.TF th{background:#ebecee url("images/bg_th.jpg") left top repeat-x;border-bottom:1px solid #d0d0d0;border-right:1px solid #d0d0d0;border-left:1px solid #fff;border-top:1px solid #fff;color:#333}table.TF td{border-bottom:1px dotted #999;padding:5px}.fltrow{background-color:#ebecee !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #666 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #999 !important}input.flt{width:99% !important}.inf{height:$min-height;background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important}input.reset{background:transparent url("images/btn_eraser.gif") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;}.nextPage:hover{background:transparent url("images/btn_over_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important;}.previousPage:hover{background:transparent url("images/btn_over_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;}.firstPage:hover{background:transparent url("images/btn_over_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;}.lastPage:hover{background:transparent url("images/btn_over_last_page.gif") center center no-repeat !important}div.grd_Cont{background-color:#ebecee !important;border:1px solid #ccc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#d5d5d5}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important;}div.grd_headTblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #999 !important}.grd_inf{background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important;border-top:1px solid #d0d0d0 !important}.loader{border:1px solid #999}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#fff}.odd{background-color:#d5d5d5}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#999 !important}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
table.TF{border-left:1px dotted #81963b;border-top:none;border-right:0;border-bottom:none;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x;border-bottom:0;border-right:1px dotted #d0d0d0;border-left:0;border-top:0;color:#fff}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px}.fltrow{background-color:#81963b !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #687830 !important}input.flt{width:99% !important}.inf{background:#d8d8d8;height:$min-height}input.reset{width:53px;background:transparent url("images/btn_filter.png") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important}div.grd_Cont{background:#81963b url("images/bg_headers.jpg") left top repeat-x !important;border:1px solid #ccc !important;padding:0 1px 1px 1px !important;}div.grd_Cont .even{background-color:#bccd83}div.grd_Cont .odd{background-color:#fff}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important;}div.grd_tblCont table td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b}div.grd_tblCont table th,div.grd_headTblCont table th{background:transparent url("images/bg_headers.jpg") 0 0 repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;padding:0 4px 0 4px !important;color:#fff !important;height:35px !important}div.grd_headTblCont table td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;background-color:#81963b !important;padding:1px 3px 1px 3px !important}.grd_inf{background-color:#d8d8d8;border-top:1px solid #d0d0d0 !important}.loader{border:0 !important;background:#81963b !important}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#bccd83}.odd{background-color:#fff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#81963b !important}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
table.TF{padding:0;color:#000;border-right:1px solid #a4bed4;border-top:1px solid #a4bed4;border-left:1px solid #a4bed4;border-bottom:0;}table.TF th{margin:0;color:inherit;background:#d1e5fe url("images/bg_skyblue.gif") 0 0 repeat-x;border-color:#fdfdfd #a4bed4 #a4bed4 #fdfdfd;border-width:1px;border-style:solid}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid #a4bed4;border-left:0;border-top:0;border-right:0}.fltrow{background-color:#d1e5fe !important;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4 !important}input.flt{width:99% !important}.inf{background-color:#e3efff !important;border:1px solid #a4bed4;height:$min-height;color:#004a6f}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#ffe4ab url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#ffe4ab url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#ffe4ab url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#ffe4ab url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.activeHeader{background:#ffe4ab !important;border:1px solid #ffb552 !important;color:inherit !important}div.grd_Cont{background-color:#d9eaed !important;border:1px solid #9cc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#e3efff}div.grd_headTblCont{background-color:#d9eaed !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#d9eaed url("images/bg_skyblue.gif") left top repeat-x;border-bottom:1px solid #a4bed4;border-right:1px solid #a4bed4 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #a4bed4 !important;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:#cce2fe;color:#004a6f;border-top:1px solid #9cc !important;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#2d8eef;border:1px solid #cce2fe;border-radius:5px}.even{background-color:#fff}.odd{background-color:#e3efff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ffdc61 !important;color:inherit}.ezSelectedRow{background-color:#ffe4ab !important;color:inherit}.ezActiveCell{background-color:#fff !important;color:#000 !important;font-weight:bold}.ezETSelectedCell{background-color:#fff !important;font-weight:bold;color:#000 !important}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.33 by Max Guglielmi
* build date: 2017-01-07T11:45:50.125Z
* tablefilter v0.4.34 by Max Guglielmi
* build date: 2017-01-15T06:21:30.968Z
* MIT License
*/
table.TF{padding:0;color:inherit;border-right:1px solid transparent;border-top:1px solid transparent;border-left:1px solid transparent;border-bottom:0;}table.TF th{margin:0;color:inherit;background-color:transparent;border-color:transparent;border-width:1px;border-style:solid;}table.TF th:last-child{border-right:1px solid transparent}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid transparent;border-left:0;border-top:0;border-right:0}.fltrow{background-color:transparent;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px;border-bottom:1px solid transparent !important;}.fltrow th:last-child,.fltrow td:last-child{border-right:1px solid transparent}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4}input.flt{width:99% !important}.inf{background-color:transparent;border:1px solid transparent;height:$min-height;color:inherit}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#f7f7f7 url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#f7f7f7 url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#f7f7f7 url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#f7f7f7 url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.activeHeader{background:#f7f7f7 !important;border:1px solid transparent;color:inherit !important}div.grd_Cont{-webkit-box-shadow:0 0 0 0 rgba(50,50,50,0.75);-moz-box-shadow:0 0 0 0 rgba(50,50,50,0.75);box-shadow:0 0 0 0 rgba(50,50,50,0.75);background-color:transparent;border:1px solid transparent;padding:0 !important;}div.grd_Cont .even{background-color:transparent}div.grd_Cont .odd{background-color:#f7f7f7}div.grd_headTblCont{background-color:transparent;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:transparent;border-bottom:1px solid transparent;border-right:1px solid transparent !important;border-left:1px solid transparent;border-top:1px solid transparent}div.grd_tblCont table td{border-bottom:1px solid transparent;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:transparent;color:inherit;border-top:1px solid transparent;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#f7f7f7;border:1px solid #f7f7f7;border-radius:5px;color:#000;text-shadow:none}.even{background-color:transparent}.odd{background-color:#f7f7f7}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ccc !important;color:inherit}.ezSelectedRow{background-color:#ccc !important;color:inherit}.ezActiveCell{background-color:transparent;color:inherit;font-weight:bold}.ezETSelectedCell{background-color:transparent;font-weight:bold;color:inherit}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{
"name": "tablefilter",
"version": "0.4.33",
"version": "0.4.34",
"description": "A Javascript library making HTML tables filterable and a bit more",
"license": "MIT",
"author": {

View file

@ -1,6 +1,7 @@
import {Feature} from '../../feature';
import {createText, elm} from '../../dom';
import {isArray, isFn, isUndef, EMPTY_FN} from '../../types';
import {isArray, isFn, isUndef, isEmpty, EMPTY_FN} from '../../types';
import {numSortAsc} from '../../sort';
const EVENTS = [
'after-filtering',
@ -8,6 +9,14 @@ const EVENTS = [
'after-page-length-change'
];
const SUM = 'sum';
const MEAN = 'mean';
const MIN = 'min';
const MAX = 'max';
const MEDIAN = 'median';
const Q1 = 'q1';
const Q3 = 'q3';
/**
* Column calculations extension
*/
@ -42,6 +51,51 @@ export default class ColOps extends Feature {
*/
this.opts = opts;
/**
* List of DOM element IDs containing column's calculation result
* @type {Array}
*/
this.labelIds = opts.id || [];
/**
* List of columns' indexes for calculations
* @type {Array}
*/
this.colIndexes = opts.col || [];
/**
* List of operations - possible values: 'sum', 'mean', 'min', 'max',
* 'median', 'q1', 'q3'
* @type {Array}
*/
this.operations = opts.operation || [];
/**
* List of write methods used to write the result - possible values:
* 'innerHTML', 'setValue', 'createTextNode'
* @type {Array}
*/
this.outputTypes = opts.write_method || [];
/**
* List of row indexes displaying the results
* @type {Array}
*/
this.totRowIndexes = opts.tot_row_index || [];
/**
* List of row indexes excluded from calculations
* @type {Array}
*/
this.excludeRows = opts.exclude_row || [];
/**
* List of decimal precision for calculation results
* @type {Array}
*/
this.decimalPrecisions = isUndef(opts.decimal_precision) ?
2 : opts.decimal_precision;
this.enable();
}
@ -53,13 +107,11 @@ export default class ColOps extends Feature {
return;
}
// subscribe to events
this.emitter.on(EVENTS, () => this.calc());
this.emitter.on(EVENTS, () => this.calcAll());
this.calc();
this.calcAll();
/**
* @inherited
*/
/** @inherited */
this.initialized = true;
}
@ -79,7 +131,7 @@ export default class ColOps extends Feature {
* (1) optimized the routine (now it will only process each column once),
* (2) added calculations for the median, lower and upper quartile.
*/
calc() {
calcAll() {
let tf = this.tf;
if (!tf.isInitialized()) {
return;
@ -88,277 +140,307 @@ export default class ColOps extends Feature {
this.onBeforeOperation(tf, this);
this.emitter.emit('before-column-operation', tf, this);
let opts = this.opts,
labelId = opts.id,
colIndex = opts.col,
operation = opts.operation,
outputType = opts.write_method,
totRowIndex = opts.tot_row_index,
excludeRow = opts.exclude_row,
decimalPrecision = isUndef(opts.decimal_precision) ?
2 : opts.decimal_precision;
let colIndexes = this.colIndexes,
colOperations = this.operations,
outputTypes = this.outputTypes,
totRowIndexes = this.totRowIndexes,
excludeRows = this.excludeRows,
decimalPrecisions = isUndef(this.decimalPrecisions) ?
2 : this.decimalPrecisions;
//nuovella: determine unique list of columns to operate on
let ucolIndex = [],
ucolMax = 0;
ucolIndex[ucolMax] = colIndex[0];
let uIndexes = [];
colIndexes.forEach((val) => {
if (uIndexes.indexOf(val) === -1) {
uIndexes.push(val);
}
});
for (let ii = 1; ii < colIndex.length; ii++) {
let saved = 0;
//see if colIndex[ii] is already in the list of unique indexes
for (let jj = 0; jj <= ucolMax; jj++) {
if (ucolIndex[jj] === colIndex[ii]) {
saved = 1;
let nbCols = uIndexes.length - 1,
rows = tf.tbl.rows,
colValues = [];
for (let u = 0; u <= nbCols; u++) {
//this retrieves col values
//use uIndexes because we only want to pass through this loop
//once for each column get the values in this unique column
colValues.push(
tf.getFilteredDataCol(uIndexes[u], false, true, excludeRows)
);
let curValues = colValues[u];
//next: calculate all operations for this column
let result = 0,
operations = [],
precisions = [],
labels = [],
writeType,
idx = 0;
for (let k = 0; k < colIndexes.length; k++) {
if (colIndexes[k] !== uIndexes[u]) {
continue;
}
operations[idx] = colOperations[k].toLowerCase();
precisions[idx] = decimalPrecisions[k];
labels[idx] = this.labelIds[k];
writeType = isArray(outputTypes) ? outputTypes[k] : null;
idx++;
}
//if not saved then, save the index;
if (saved === 0) {
ucolMax++;
ucolIndex[ucolMax] = colIndex[ii];
}
}
if (isArray(labelId) && isArray(colIndex) && isArray(operation)) {
let rows = tf.tbl.rows,
colvalues = [],
ucol = 0;
for (; ucol <= ucolMax; ucol++) {
//this retrieves col values
//use ucolIndex because we only want to pass through this loop
//once for each column get the values in this unique column
colvalues.push(
tf.getColValues(ucolIndex[ucol], false, true, excludeRow)
for (let i = 0; i <= idx; i++) {
// emit values before column calculation
this.emitter.emit(
'before-column-calc',
tf,
this,
uIndexes[u],
curValues,
operations[i],
precisions[i]
);
//next: calculate all operations for this column
let result,
nbvalues = 0,
temp,
meanValue = 0,
sumValue = 0,
minValue = null,
maxValue = null,
q1Value = null,
medValue = null,
q3Value = null,
meanFlag = 0,
sumFlag = 0,
minFlag = 0,
maxFlag = 0,
q1Flag = 0,
medFlag = 0,
q3Flag = 0,
theList = [],
opsThisCol = [],
decThisCol = [],
labThisCol = [],
oTypeThisCol = [],
mThisCol = -1,
k = 0,
j = 0,
i = 0;
result = Number(this.calc(curValues, operations[i], null));
for (; k < colIndex.length; k++) {
if (colIndex[k] === ucolIndex[ucol]) {
mThisCol++;
opsThisCol[mThisCol] = operation[k].toLowerCase();
decThisCol[mThisCol] = decimalPrecision[k];
labThisCol[mThisCol] = labelId[k];
oTypeThisCol = isArray(outputType) ?
outputType[k] : null;
// emit column calculation result
this.emitter.emit(
'column-calc',
tf,
this,
uIndexes[u],
result,
operations[i],
precisions[i]
);
switch (opsThisCol[mThisCol]) {
case 'mean':
meanFlag = 1;
break;
case 'sum':
sumFlag = 1;
break;
case 'min':
minFlag = 1;
break;
case 'max':
maxFlag = 1;
break;
case 'median':
medFlag = 1;
break;
case 'q1':
q1Flag = 1;
break;
case 'q3':
q3Flag = 1;
break;
}
}
}
// write result in expected DOM element
this.writeResult(
result,
labels[i],
writeType,
precisions[i]
);
for (; j < colvalues[ucol].length; j++) {
//sort the list for calculation of median and quartiles
if ((q1Flag === 1) || (q3Flag === 1) || (medFlag === 1)) {
if (j < colvalues[ucol].length - 1) {
for (k = j + 1; k < colvalues[ucol].length; k++) {
/* eslint-disable */
if (eval(colvalues[ucol][k]) <
eval(colvalues[ucol][j])) {
/* eslint-enable */
temp = colvalues[ucol][j];
colvalues[ucol][j] = colvalues[ucol][k];
colvalues[ucol][k] = temp;
}
}
}
}
let cvalue = parseFloat(colvalues[ucol][j]);
theList[j] = parseFloat(cvalue);
}//for i
if (!isNaN(cvalue)) {
nbvalues++;
if (sumFlag === 1 || meanFlag === 1) {
sumValue += parseFloat(cvalue);
}
if (minFlag === 1) {
if (minValue === null) {
minValue = parseFloat(cvalue);
} else {
minValue = parseFloat(cvalue) < minValue ?
parseFloat(cvalue) : minValue;
}
}
if (maxFlag === 1) {
if (maxValue === null) {
maxValue = parseFloat(cvalue);
} else {
maxValue = parseFloat(cvalue) > maxValue ?
parseFloat(cvalue) : maxValue;
}
}
}
}//for j
if (meanFlag === 1) {
meanValue = sumValue / nbvalues;
}
if (medFlag === 1) {
let aux = 0;
if (nbvalues % 2 === 1) {
aux = Math.floor(nbvalues / 2);
medValue = theList[aux];
} else {
medValue = (theList[nbvalues / 2] +
theList[((nbvalues / 2) - 1)]) / 2;
}
}
let posa;
if (q1Flag === 1) {
posa = 0.0;
posa = Math.floor(nbvalues / 4);
if (4 * posa === nbvalues) {
q1Value = (theList[posa - 1] + theList[posa]) / 2;
} else {
q1Value = theList[posa];
}
}
if (q3Flag === 1) {
posa = 0.0;
let posb = 0.0;
posa = Math.floor(nbvalues / 4);
if (4 * posa === nbvalues) {
posb = 3 * posa;
q3Value = (theList[posb] + theList[posb - 1]) / 2;
} else {
q3Value = theList[nbvalues - posa - 1];
}
}
for (; i <= mThisCol; i++) {
switch (opsThisCol[i]) {
case 'mean':
result = meanValue;
break;
case 'sum':
result = sumValue;
break;
case 'min':
result = minValue;
break;
case 'max':
result = maxValue;
break;
case 'median':
result = medValue;
break;
case 'q1':
result = q1Value;
break;
case 'q3':
result = q3Value;
break;
}
let precision = !isNaN(decThisCol[i]) ? decThisCol[i] : 2;
//if outputType is defined
if (oTypeThisCol && result) {
result = result.toFixed(precision);
if (elm(labThisCol[i])) {
switch (oTypeThisCol.toLowerCase()) {
case 'innerhtml':
if (isNaN(result) || !isFinite(result) ||
nbvalues === 0) {
elm(labThisCol[i]).innerHTML = '.';
} else {
elm(labThisCol[i]).innerHTML = result;
}
break;
case 'setvalue':
elm(labThisCol[i]).value = result;
break;
case 'createtextnode':
let oldnode =
elm(labThisCol[i]).firstChild;
let txtnode = createText(result);
elm(labThisCol[i])
.replaceChild(txtnode, oldnode);
break;
}//switch
}
} else {
try {
if (isNaN(result) || !isFinite(result) ||
nbvalues === 0) {
elm(labThisCol[i]).innerHTML = '.';
} else {
elm(labThisCol[i]).innerHTML =
result.toFixed(precision);
}
} catch (e) { }//catch
}//else
}//for i
// row(s) with result are always visible
let totRow = totRowIndex && totRowIndex[ucol] ?
rows[totRowIndex[ucol]] : null;
if (totRow) {
totRow.style.display = '';
}
}//for ucol
}//if typeof
// row(s) with result are always visible
let totRow = totRowIndexes && totRowIndexes[u] ?
rows[totRowIndexes[u]] : null;
if (totRow) {
totRow.style.display = '';
}
}//for u
this.onAfterOperation(tf, this);
this.emitter.emit('after-column-operation', tf, this);
}
/**
* Remove extension
* Make desired calculation on specified column.
* @param {Number} colIndex Column index
* @param {any} [operation=SUM] Operation type
* @param {any} precision Decimal precision
* @returns {Number}
*/
columnCalc(colIndex, operation = SUM, precision) {
let excludeRows = this.excludeRows || [];
let colValues =
this.tf.getFilteredDataCol(colIndex, false, true, excludeRows);
return this.calc(colValues, operation, precision);
}
/**
* Make calculation on passed values.
* @param {Array} values List of values
* @param {String} [operation=SUM] Optional operation type
* @param {Number} precision Optional result precision
* @returns {Number}
* @private
*/
calc(colValues, operation = SUM, precision) {
let result = 0;
if (operation === Q1 || operation === Q3 || operation === MEDIAN) {
colValues = this.sortColumnValues(colValues, numSortAsc);
}
switch (operation) {
case MEAN:
result = this.calcMean(colValues);
break;
case SUM:
result = this.calcSum(colValues);
break;
case MIN:
result = this.calcMin(colValues);
break;
case MAX:
result = this.calcMax(colValues);
break;
case MEDIAN:
result = this.calcMedian(colValues);
break;
case Q1:
result = this.calcQ1(colValues);
break;
case Q3:
result = this.calcQ3(colValues);
break;
}
return isEmpty(precision) ? result : result.toFixed(precision);
}
/**
* Calculate the sum of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcSum(values = []) {
if (isEmpty(values)) {
return 0;
}
let result = values.reduce((x, y) => x + y);
return Number(result);
}
/**
* Calculate the mean of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMean(values = []) {
let result = this.calcSum(values) / values.length;
return Number(result);
}
/**
* Calculate the max value of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMax(values = []) {
return Math.max.apply(null, values);
}
/**
* Calculate the min value of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMin(values = []) {
return Math.min.apply(null, values);
}
/**
* Calculate the median of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMedian(values = []) {
let nbValues = values.length;
let aux = 0;
if (nbValues % 2 === 1) {
aux = Math.floor(nbValues / 2);
return Number(values[aux]);
}
return Number(
(values[nbValues / 2] +
values[((nbValues / 2) - 1)]) / 2
);
}
/**
* Calculate the lower quartile of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcQ1(values = []) {
let nbValues = values.length;
let posa = 0.0;
posa = Math.floor(nbValues / 4);
if (4 * posa === nbValues) {
return Number(
(values[posa - 1] + values[posa]) / 2
);
}
return Number(values[posa]);
}
/**
* Calculate the upper quartile of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcQ3(values = []) {
let nbValues = values.length;
let posa = 0.0;
let posb = 0.0;
posa = Math.floor(nbValues / 4);
if (4 * posa === nbValues) {
posb = 3 * posa;
return Number(
(values[posb] + values[posb - 1]) / 2
);
}
return Number(values[nbValues - posa - 1]);
}
/**
* Sort passed values with supplied sorter function.
* @param {Array} [values=[]] List of values to be sorted
* @param {Function} sorter Sorter function
* @returns {Array}
*/
sortColumnValues(values = [], sorter) {
return values.sort(sorter);
}
/**
* Write calculation result in passed DOM element with supplied write method
* and decimal precision.
* @param {Number} [result=0] Calculation result
* @param {DOMElement} label DOM element
* @param {String} [writeType='innerhtml'] Write method
* @param {Number} [precision=2] Applied decimal precision
* @private
*/
writeResult(result = 0, label, writeType = 'innerhtml', precision = 2) {
let labelElm = elm(label);
if (!labelElm) {
return;
}
result = result.toFixed(precision);
if (isNaN(result) || !isFinite(result)) {
result = '';
}
switch (writeType.toLowerCase()) {
case 'innerhtml':
labelElm.innerHTML = result;
break;
case 'setvalue':
labelElm.value = result;
break;
case 'createtextnode':
let oldNode = labelElm.firstChild;
let txtNode = createText(result);
labelElm.replaceChild(txtNode, oldNode);
break;
}
}
/** Remove extension */
destroy() {
if (!this.initialized) {
return;
}
// unsubscribe to events
this.emitter.off(EVENTS, () => this.calc());
this.emitter.off(EVENTS, () => this.calcAll());
this.initialized = false;
}

View file

@ -2107,7 +2107,7 @@ export class TableFilter {
if (nchilds === this.nbCells && !isExludedRow) {
// this loop retrieves cell data
for (let j = 0; j < nchilds; j++) {
if (j !== colIndex || row[i].style.display !== '') {
if (j !== colIndex) {
continue;
}
let cellData = this.getCellData(cell[j]);
@ -2353,28 +2353,55 @@ export class TableFilter {
* Return the filtered data for a given column index
* @param {Number} colIndex Colmun's index
* @param {Boolean} includeHeaders Optional: include headers row
* @param {Boolean} num Optional: return unformatted number
* @param {Array} exclude Optional: list of row indexes to be excluded
* @param {Boolean} visible Optional: return only visible data
* (relevant for paging)
* @return {Array} Flat list of values ['val0','val1','val2'...]
*
* TODO: provide an API returning data in JSON format
*/
getFilteredDataCol(colIndex, includeHeaders = false) {
getFilteredDataCol(
colIndex,
includeHeaders = false,
num = false,
exclude = [],
visible = true
) {
if (isUndef(colIndex)) {
return [];
}
let data = this.getFilteredData(),
colData = [];
let rows = this.tbl.rows;
// ensure valid rows index do not contain excluded rows and row is
// displayed
let validRows = this.getValidRows(true).filter((rowIdx) => {
return exclude.indexOf(rowIdx) === -1 &&
(visible ?
this.getRowDisplay(rows[rowIdx]) !== 'none' :
true);
});
let decimal = this.decimalSeparator;
if (this.hasType(colIndex, [FORMATTED_NUMBER])) {
let colType = this.colTypes[colIndex];
if (colType.hasOwnProperty('decimal')) {
decimal = colType.decimal;
}
}
// convert column value to expected type if necessary
let validColValues = validRows.map((rowIdx) => {
let val = this.getCellData(rows[rowIdx].cells[colIndex]);
return num ? Number(val) || parseNb(val, decimal) : val;
});
if (includeHeaders) {
colData.push(this.getHeadersText()[colIndex]);
validColValues.unshift(this.getHeadersText()[colIndex]);
}
for (let i = 0, len = data.length; i < len; i++) {
let r = data[i],
//cols values of current row
d = r[1],
//data of searched column
c = d[colIndex];
colData.push(c);
}
return colData;
return validColValues;
}
/**

View file

@ -63,7 +63,7 @@ export const isUndef = (obj) => obj === UNDEFINED;
* @param {Any} obj
* @return {Boolean}
*/
export const isNull = obj => obj === null;
export const isNull = (obj) => obj === null;
/**
* Check passed argument is empty (undefined, null or empty string)

View file

@ -350,4 +350,4 @@
<td>88.233.19.89</td>
</tr>
</tbody>
</table>
</table>

View file

@ -101,6 +101,7 @@ test('Column operations', function() {
equal(id('q1-2').innerHTML, 1.10, 'Q1 result');
equal(id('q3-1').innerHTML, 2045, 'Q3 result');
equal(id('q3-2').innerHTML, 2.15, 'Q3 result');
tf.clearFilters();
});
module('Behaviour checks');