Here is the plugin:
(function($) {
$.fn.accumulate = function(options) {
options = options || {};
function view(row) {
var t = [];
t.push('');
for (var i = 0; i < row.meta.columnCount; i++) { t.push('');
t.push('');
if (columnHasFixedDisplay(i)) {
t.push(options["col" + i].display);
}
else {
if (row.data[i]) {
var value = columnHasAverageValue(i) ? (row.data[i].total / (row.data[i].count)) : row.data[i].total;
t.push(columnHasFixedDisplayFunction(i) ? options["col" + i].displayFunction(value) : value);
}
}
t.push('');
t.push('');
}
t.push('');
return t.join('');
}
//defaults to sum
function columnHasAverageValue(i) {
return options["col" + i] && "average" == options["col" + i].type;
}
function columnHasFixedDisplay(i) {
return options["col" + i] && options["col" + i].display;
}
function columnHasFixedDisplayFunction(i) {
return options["col" + i] && options["col" + i].displayFunction;
}
function columnHasAccumulatorFunction(i) {
return options["col" + i] && options["col" + i].accumulatorFunction;
}
return this.each(function() {
var $this = $(this);
var rows = $("tbody tr", $this);
var accumulatedRow = {
meta: {
rowCount: rows.length,
columnCount: 0
},
data: {}
};
rows.each(function() {
var $columns = $('td', $(this));
accumulatedRow.meta.columnCount = $columns.length;
for (var i = 0; i < $columns.length; i++) { var value = $columns[i].innerHTML; if (columnHasAccumulatorFunction(i)) { accumulatedRow.data[i] = options["col" + i].accumulatorFunction(accumulatedRow.data[i], value) } else{ if (NG.isNumeric(value)) { if (!accumulatedRow.data[i]) { accumulatedRow.data[i] = { count: 0, total: (NG.isFloat(value) ? 0 : 0.0) }; } accumulatedRow.data[i].count++; accumulatedRow.data[i].total += NG.isFloat(value) ? parseFloat(value) : parseInt(value); } } } }); $("tbody", $this).append(view(accumulatedRow)); }); }; })(jQuery);
Here are the helper methods, you can keep them under a namespace maybe, thats how I do:
isNumeric: function(input) {
var RE = /^-{0,1}\d*\.{0,1}\d+$/;
return (RE.test(input));
}
isFloat: function(input) {
return /\./.test(input.toString());
}
Here is the usage, the jquery object is the table structured well with tbody:
$("#table-id").accumulate({
"col0": {
display: "Total",
style: "text-align: left;"
},
"col1": {
accumulatorFunction: function(accumulatedValue, value) {
if (!accumulatedValue) {
accumulatedValue = {
total: {
firstEleven: 0,
sub: 0
},
count: 0
}
}
var s = value.replace(' ', '').replace(')', '').split('(');
accumulatedValue.count++;
accumulatedValue.total.firstEleven += parseInt(s[0]);
accumulatedValue.total.sub += 1 <>
Default behaviour is to sum up every numeric value, you can specify a fix display for a column, to play with the display value, I added a display function and as I had values like 9 (10) in some columns and since they are not numeric I had to add a accumulator function. Anyway I ll update it if I ever need to add more functionality.
Later.
Sorry for the spacing, didn't have time to find out why this happened when I copied and pasted. I surely don't write code without formating!
ReplyDelete