Th doesn't sort Tbody on some modified column - javascript

I have multiple tbody in a table which some of span columns and rows. And then I got a jQuery code to sort this tbody based on the th.data- click.
In the first th column when it is clicked it will sort correctly. However, in the second th column when it is clicked it does not sort the tbody.
Here is the snippet :
var table = $('table'),
th = table.find('thead th'),
tbody = table.find('tbody');
$(th).on('click', function() {
$(th).removeClass();
var index = this.cellIndex,
sortType = $(this).data('sort'),
sortDir = $(this).data('dir') || 'asc';
var that = $(this);
$('table').find('tbody').slice().sort(function(a, b) {
var dataTH = that.data('class');
//alert(dataTH);
if(dataTH == 'number')
{
//alert("hi this is a number");
var aText = $(a).find('td.sortNum:eq(' + index + ')').text(),
bText = $(b).find('td.sortNum:eq(' + index + ')').text();
}
else if(dataTH == 'department')
{
//alert("hi this is a department");
var aText = $(a).find('td.depart:eq(' + index + ')').text(),
bText = $(b).find('td.depart:eq(' + index + ')').text();
}
if (sortDir == 'desc') {
temp = aText;
aText = bText;
bText = temp;
}
if (sortType == 'string') {
return aText.localeCompare(bText);
}
else {
return +aText - +bText;
}
})
.appendTo('table');
$(this).data('dir', sortDir == 'asc' ? 'desc' : 'asc');
$(this).removeClass().addClass('sort-' + sortDir);
});
table {
border-collapse: collapse;
width: 400px;
}
th, td {
padding: 5px;
border: 1px #DDD solid;
}
.sort-asc:after,
.sort-desc:after {
content: '▲';
font-size: 12px;
}
.sort-desc:after {
content: '▼';
}
<table>
<thead>
<tr>
<th data-sort="number" data-class="number" >No</th>
<th data-sort="number" data-class="department" >Department</th>
<th data-sort="number">Quantity</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2" class="sortNum">1</td>
<td class="depart">20</td>
<td>20</td>
</tr>
<tr>
<td colspan="2" style="text-align:center">VTP</td>
</tr>
</tbody>
<tbody>
<tr>
<td rowspan="2" class="sortNum">2</td>
<td class="depart">30</td>
<td>25</td>
</tr>
<tr>
<td colspan="2" style="text-align:center">VTP</td>
</tr>
</tbody>
<tbody>
<tr>
<td rowspan="2" class="sortNum">3</td>
<td class="depart">40</td>
<td>50</td>
</tr>
<tr>
<td colspan="2" style="text-align:center">VTP</td>
</tr>
</tbody>
<tbody>
<tr>
<td rowspan="2" class="sortNum">4</td>
<td class="depart">50</td>
<td>15</td>
</tr>
<tr>
<td colspan="2" style="text-align:center">VTP</td>
</tr>
</tbody>
<tbody>
<tr>
<td rowspan="2" class="sortNum">5</td>
<td class="depart">60</td>
<td>32</td>
</tr>
<tr>
<td colspan="2" style="text-align:center">VTP</td>
</tr>
</tbody>
</table>

You do not need the :eq Selector since you are referencing the Cells by css class. It does work in the first Column because the cell index is zero. What you are essentially saying in the selector $(a).find('td.sortNum:eq(' + index + ')') is "give me the list of td's with the class 'sortNum' and of that list the element at position index. But the first condition of the Selector - td.sortNum - will only return one element.
To make your sorting work again for the second column you could get rid of the :eq part
if(dataTH == 'number')
{
//alert("hi this is a number");
var aText = $(a).find('td.sortNum').text(),
bText = $(b).find('td.sortNum').text();
}
else if(dataTH == 'department')
{
//alert("hi this is a department");
var aText = $(a).find('td.depart').text(),
bText = $(b).find('td.depart').text();
}
see also http://jsfiddle.net/doc_snyder/Lvvmow8g/1/

Related

How to create a table with cells not clickable

I need to make a table to select the filters of an array with conditions here for example the beginning of the table for the filters (you cannot select client and user at the same time) :
to do this i create a table with id by cell :
jQuery(document).ready(function($) {
filter = {
date: 0,
client: 0,
user: 0
};
$(".blank_row > td").click(function() {
if (filter['date'] == 0 && $(this).attr('id') == 'date') {
filter[$(this).attr('id')] = 1;
$(this).addClass("bg-success");
}
else if (filter['date'] == 1 && $(this).attr('id') == 'date') {
$(this).removeClass("bg-success");
filter[$(this).attr('id')] = 0;
}
if (filter['client'] == 0 && filter['user'] == 0 && $(this).attr('id') != 'date') {
filter[$(this).attr('id')] = 1;
$(this).addClass("bg-success");
} else if (filter['client'] == 1 || filter['user'] == 1) {
$(this).removeClass("bg-success");
filter[$(this).attr('id')] = 0;
}
console.log($(this).attr('id'));
console.log(filter);
});
});
.blank_row {
height: 50px !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<table id="graphTable" class="table table-sm table-bordered">
<thead>
<tr>
<th class="border" colspan="3">FILTER</th>
</tr>
<tr>
<th>DATE</th>
<th>CLIENT</th>
<th>USER</th>
</tr>
</thead>
<tbody>
<tr class="blank_row">
<td id="date"></td>
<td id="client"></td>
<td id="user"></td>
</tr>
</tbody>
</table>
but if i want to add new cells i would be quickly lost with the code i already made. Do you have any other solution to do what I want more simply?
You can use hasClass method of jquery to see if the tds have required class or not depending on that we can addClass or removeClass from any particular tds.
Demo code :
$(document).ready(function($) {
$(".blank_row > td").click(function() {
//get td closest tr(index)
var rowIndex = $(this).closest("tr").index();
//getting cell no of td which is clicked
var cell = $(this).index();
//looping over the tr
$('tbody > tr:eq(' + rowIndex + ') ').each(function(cellIndex){
var selectors = $(this).find("td:eq(" + cell + ")");
//checking if the clicked td has some classes or not
if (!(selectors.hasClass("bg-success")) && (selectors.hasClass("date"))) {
//add
selectors.addClass("bg-success");
} else if (selectors.hasClass("date") && selectors.hasClass("bg-success")) {
//removed
selectors.removeClass("bg-success");
}
//checking if the client and user has bg-success or not
if (!($(this).find(".client").hasClass('bg-success')) && !($(this).find(".user").hasClass('bg-success')) && !(selectors.hasClass("date"))) {
//add
selectors.addClass("bg-success");
} else if ((($(this).find(".client").hasClass('bg-success')) || ($(this).find(".user").hasClass('bg-success'))) && !(selectors.hasClass("date"))) {
//removed
selectors.removeClass("bg-success");
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />
<table id="graphTable" class="table table-sm table-bordered">
<thead>
<tr>
<th class="border" colspan="3">FILTER</th>
</tr>
<tr>
<th>DATE</th>
<th>CLIENT</th>
<th>USER</th>
</tr>
</thead>
<tbody>
<tr class="blank_row">
<td class="date">a</td>
<td class="client">b</td>
<td class="user">c</td>
</tr>
<tr class="blank_row">
<td class="date">a1</td>
<td class="client">b1</td>
<td class="user">c1</td>
</tr>
<tr class="blank_row">
<td class="date">a2</td>
<td class="client">b2</td>
<td class="user">c2</td>
</tr>
</tbody>
</table>

How do I sum the price column from HTML table using JavaScript?

I am trying to add Price from table column to a total.
I am having problem adding values such as 10.00 or 5.99. I am able to calculate prices with int values, but not with values 10.00 or 5.99, etc.
Here is what I have below.
var table = document.getElementById("myTable"),
sumVal = 0;
for (var i = 1; i < table.rows.length; i++) {
sumVal = sumVal + parseF(table.rows[i].cells[2].innerHTML);
}
document.getElementById("val").innerHTML = "SubTotal =" + sumVal;
console.log(sumVal);
<table id="myTable">
<tr>
<th>Item</th>
<th>Price</th>
<th>Remove</th>
</tr>
<tr>
<td>Hoddie</td>
<td class="count-me">15.00</td>
<td><button onClick="myFunction()">Remove</button></td>
</tr>
<tr>
<td>Nike Cap</td>
<td class="count-me">10.99</td>
<td><button onClick="myFunction()">Remove</button></td>
</tr>
</table>
<span id="val"></span>
You have three issues:
You are grabbing the wrong cell index, indices start at 0:
table.rows[i].cells[1]
You need to call the correct parse function:
parseFloat(table.rows[i].cells[1].innerHTML);
You need to format your output:
"SubTotal = $" + sumVal.toFixed(2);
Update: Added functionality for removing rows.
updateSubTotal(); // Initial call
function updateSubTotal() {
var table = document.getElementById("myTable");
let subTotal = Array.from(table.rows).slice(1).reduce((total, row) => {
return total + parseFloat(row.cells[1].innerHTML);
}, 0);
document.getElementById("val").innerHTML = "SubTotal = $" + subTotal.toFixed(2);
}
function onClickRemove(deleteButton) {
let row = deleteButton.parentElement.parentElement;
row.parentNode.removeChild(row);
updateSubTotal(); // Call after delete
}
#myTable td {
padding: 0.25em;
}
#val {
display: block;
margin-top: 0.5em;
}
<table id="myTable">
<tr>
<th>Item</th>
<th>Price</th>
<th>Remove</th>
</tr>
<tr>
<td>Hoodie</td>
<td class="count-me">15.00</td>
<td><button onClick="onClickRemove(this)">Remove</button></td>
</tr>
<tr>
<td>Nike Cap</td>
<td class="count-me">10.99</td>
<td><button onClick="onClickRemove(this)">Remove</button></td>
</tr>
</table>
<span id="val"></span>
You are accessing the incorrect array element and also need to use parseFloat
The cells array is zero-based so you need to use cells[1] to access the second column:
var table = document.getElementById("myTable"),
sumVal = 0;
for (var i = 1; i < table.rows.length; i++) {
sumVal = sumVal + parseFloat(table.rows[i].cells[1].innerHTML);
}
document.getElementById("val").innerHTML = "SubTotal =" + sumVal;
console.log(sumVal);
<table id="myTable">
<tr>
<th>Item</th>
<th>Price</th>
<th>Remove</th>
</tr>
<tr>
<td>Hoddie</td>
<td class="count-me">15.00</td>
<td><button onClick="myFunction()">Remove</button></td>
</tr>
<tr>
<td>Nike Cap</td>
<td class="count-me">10.99</td>
<td><button onClick="myFunction()">Remove</button></td>
</tr>
</table>
<span id="val"></span>
updateSubTotal(); // Initial call
function updateSubTotal() {
var table = document.getElementById("myTable");
let subTotal = Array.from(table.rows).slice(1).reduce((total, row) => {
return total + parseFloat(row.cells[1].innerHTML);
}, 0);
let subTotal2 = Array.from(table.rows).slice(1).reduce((total, row) => {
return total + parseFloat(row.cells[2].innerHTML);
}, 0);
document.getElementById("val").innerHTML = "SubTotal = $" + subTotal.toFixed(2);
document.getElementById("val1").innerHTML = subTotal2.toFixed(2);
}
function onClickRemove(deleteButton) {
let row = deleteButton.parentElement.parentElement;
row.parentNode.removeChild(row);
updateSubTotal(); // Call after delete
}
#myTable td {
padding: 0.25em;
}
#val {
display: block;
margin-top: 0.5em;
}
<table id="myTable">
<tr>
<th>Item</th>
<th>Price</th>
<th>M2</th>
<th>Remove</th>
</tr>
<tr>
<td>Hoodie</td>
<td class="count-me">15.00</td>
<td class="count-me">34.00</th>
<td><button onClick="onClickRemove(this)">Remove</button></td>
</tr>
<tr>
<td>Nike Cap</td>
<td class="count-me">10.99</td>
<td class="count-me">22.34</th>
<td><button onClick="onClickRemove(this)">Remove</button></td>
</tr>
</table>
<span id="val"></span>
<span id="val1"></span>
var cell = document.getElementsByClassName("count-me");
var val = 0;
var i = 0;
while (cell[i] != undefined) {
val += parseFloat(cell[i].innerHTML);
i++;
} //end while
document.getElementById("val").innerHTML = parseFloat(val).toFixed(2);
console.log(parseFloat(val).toFixed(2));
<table id="myTable">
<tr>
<th>Item</th>
<th>Price</th>
<th>Remove</th>
</tr>
<tr id="">
<td>Hoddie</td>
<td class="count-me">15.00</td>
<td>
<button onClick="myFunction()">Remove</button>
</td>
</tr>
<tr>
<td>Nike Cap</td>
<td class="count-me">10.99</td>
<td>
<button onClick="myFunction()">Remove</button>
</td>
</tr>
</table>
<span id="val"></span>

jQuery - Remove and group from HTML table

i have a dynamic table like this:
<table cellspacing="0" cellpadding="0">
<col width="80" span="3">
<tr id="id-1">
<th colspan="3" width="240">TITLE-1</th>
</tr>
<tr>
<td>val-1</td>
<td>val-2</td>
<td>val-3</td>
</tr>
<tr id="id-1">
<th colspan="3">TITLE-1</th>
</tr>
<tr>
<td>val-2</td>
<td>val-2</td>
<td>val-3</td>
</tr>
<tr id="id-2">
<th colspan="3">TITLE-2</th>
</tr>
<tr>
<td>val-1</td>
<td>val-2</td>
<td>val-2</td>
</tr>
</table>
In this table is 3 TR element with same ID. i want to remove all TR except first TR.
If not is duplicate IDs nothing change with this TR.
And i need also: in TR's is 3 td's. result must be next. if value is same group this td's:
<tr>
<td>val-2</td>
<td>val-2</td>
<td>val-3</td>
</tr>
result
<tr>
<td colspan="2">val-2</td>
<td>val-3</td>
</tr>
tnx
i changed id > class
$(".idxx:gt(0)").remove();
I did a function to parse tr's and td's. See here http://jsfiddle.net/mig1098/qo4xvqjm/ :
var mapTable={
_tr:function(){
var tabletr = $('table tr');
var compareid = '';
tabletr.each(function(){
var id = $(this).attr('id');
if(typeof id != 'undefined'){
if(compareid == ''){
compareid = id;
}else if(compareid == id){
$('#'+id).next().remove();
$('#'+id).remove();
}
}
});
},
_td:function(){
tabletr = $('table tr');
tabletr.each(function(){
var tdtext = {"obj":"","txt":"","count":1};
console.log($(this).find('th').text());
$(this).find('td').each(function(){
var td = $(this);
if(tdtext.txt == ''){
tdtext.txt = td.text();
tdtext.obj = td;
}else if(tdtext.txt == td.text()){
tdtext.count +=1;
td.hide();
td.addClass('todelete');
}else{
//before to change
tdtext.obj.attr('colspan',tdtext.count);
//
tdtext = {"obj":td,"txt":td.text(),"count":1};
}
});
if(tdtext.count > 1){
tdtext.obj.attr('colspan',tdtext.count);
}
$('.todelete').remove();
});
},
init(){
mapTable._tr();
mapTable._td();
}
}

merging <td> rows in one column of html table

I have a requirement, if i have same data in column1 of 's with same id then i need to merge those cells and show their respective values in column2.
i.e., in fiddle http://jsfiddle.net/7t9qkLc0/12/ the key column have 3rows with data 1 as row value with same id and has corresponding different values in Value column i.e., AA,BB,CC. I want to merge the 3 rows in key Column and display data 1 only once and show their corresponding values in separate rows in value column.
Similarly for data4 and data5 the values are same i.e.,FF and keys are different, i want to merge last 2 rows in Value column and dispaly FF only one time and show corresponding keys in key column. All data i'm getting would be the dynamic data. Please suggest.
Please find the fiddle http://jsfiddle.net/7t9qkLc0/12/
Sample html code:
<table width="300px" height="150px" border="1">
<tr><th>Key</th><th>Value</th></tr>
<tr>
<td id="1">data 1</td>
<td id="aa">AA</td>
</tr>
<tr>
<td id="1">data 1</td>
<td id="bb">BB</td>
</tr>
<tr>
<td id="1">data 1</td>
<td id="cc">CC</td>
</tr>
<tr>
<td id="2">data 2</td>
<td id="dd">DD</td>
</tr>
<tr>
<td id="2">data 2</td>
<td id="ee">EE</td>
</tr>
<tr>
<td id="3">data 3</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="4">data 4</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="5">data 5</td>
<td id="ff">FF</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" style="padding-left: 0px; padding-right: 0px; padding-bottom: 0px">
</td>
</tr>
</table>
Building on tkounenis' answer using Rowspan:
One option to implement what you need would be to read all the values in your table after being populated, then use a JS object literal as a data structure to figure out what rows/columns are unique.
A JS object literal requires a unique key which you can map values to. After figuring out what rows/columns should be grouped, you can either edit the original table, or hide the original table and create a new table (I'm creating new tables in this example).
I've created an example for you to create a new table either grouped by key or grouped by value. Try to edit the examples provided to introduce both requirements.
Let me know if you need more help. Best of luck.
JSFiddle: http://jsfiddle.net/biz79/x417905v/
JS (uses jQuery):
sortByCol(0);
sortByCol(1);
function sortByCol(keyCol) {
// keyCol = 0 for first col, 1 for 2nd col
var valCol = (keyCol === 0) ? 1 : 0;
var $rows = $('#presort tr');
var dict = {};
var col1name = $('th').eq(keyCol).html();
var col2name = $('th').eq(valCol).html();
for (var i = 0; i < $rows.length; i++) {
if ($rows.eq(i).children('td').length > 0) {
var key = $rows.eq(i).children('td').eq(keyCol).html();
var val = $rows.eq(i).children('td').eq(valCol).html();
if (key in dict) {
dict[key].push(val);
} else {
dict[key] = [val];
}
}
}
redrawTable(dict,col1name,col2name);
}
function redrawTable(dict,col1name,col2name) {
var $table = $('<table>').attr("border",1);
$table.css( {"width":"300px" } );
$table.append($('<tr><th>' +col1name+ '</th><th>' +col2name+ '</th>'));
for (var prop in dict) {
for (var i = 0, len = dict[prop].length; i< len; i++) {
var $row = $('<tr>');
if ( i == 0) {
$row.append( $("<td>").attr('rowspan',len).html( prop ) );
$row.append( $("<td>").html( dict[prop][i] ) );
}
else {
$row.append( $("<td>").html( dict[prop][i] ) );
}
$table.append($row);
}
}
$('div').after($table);
}
Use the rowspan attribute like so:
<table width="300px" height="150px" border="1">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr>
<td id="1" rowspan="3">data 1</td>
<td id="aa">AA</td>
</tr>
<tr>
<td id="bb">BB</td>
</tr>
<tr>
<td id="cc">CC</td>
</tr>
<tr>
<td id="2" rowspan="2">data 2</td>
<td id="dd">DD</td>
</tr>
<tr>
<td id="ee">EE</td>
</tr>
<tr>
<td id="3">data 3</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="4">data 4</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="5">data 5</td>
<td id="ff">FF</td>
</tr>
</table>
http://jsfiddle.net/37b793pz/4/
Can not be used more than once the same id. For that use data-id attribute
HTML:
<table width="300px" height="150px" border="1">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valaa">AA</td>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valbb">BB</td>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valcc">CC</td>
</tr>
<tr>
<td data-id="key2">data 2</td>
<td data-id="valdd">DD</td>
</tr>
<tr>
<td data-id="key2">data 2</td>
<td data-id="valee">EE</td>
</tr>
<tr>
<td data-id="key3">data 3</td>
<td data-id="valff">FF</td>
</tr>
<tr>
<td data-id="key4">data 4</td>
<td data-id="valff">FF</td>
</tr>
<tr>
<td data-id="key5">data 5</td>
<td data-id="valff">FF</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" style="padding-left: 0px; padding-right: 0px; padding-bottom: 0px"></td>
</tr>
</table>
JQ:
//merge cells in key column
function mergerKey() {
// prevents the same attribute is used more than once Ip
var idA = [];
// finds all cells id column Key
$('td[data-id^="key"]').each(function () {
var id = $(this).attr('data-id');
// prevents the same attribute is used more than once IIp
if ($.inArray(id, idA) == -1) {
idA.push(id);
// finds all cells that have the same data-id attribute
var $td = $('td[data-id="' + id + '"]');
//counts the number of cells with the same data-id
var count = $td.size();
if (count > 1) {
//If there is more than one
//then merging
$td.not(":eq(0)").remove();
$td.attr('rowspan', count);
}
}
})
}
//similar logic as for mergerKey()
function mergerVal() {
var idA = [];
$('td[data-id^="val"]').each(function () {
var id = $(this).attr('data-id');
if ($.inArray(id, idA) == -1) {
idA.push(id);
var $td = $('td[data-id="' + id + '"]');
var count = $td.size();
if (count > 1) {
$td.not(":eq(0)").remove();
$td.attr('rowspan', count);
}
}
})
}
mergerKey();
mergerVal();
Use below snippet of javascript. It should work fine for what you are looking.
<script type="text/javascript">
function mergeCommonCells(table, columnIndexToMerge){
previous = null;
cellToExtend = null;
table.find("td:nth-child("+columnIndexToMerge+")").each(function(){
jthis = $(this);
content = jthis.text();
if(previous == content){
jthis.remove();
if(cellToExtend.attr("rowspan") == undefined){
cellToExtend.attr("rowspan", 2);
}
else{
currentrowspan = parseInt(cellToExtend.attr("rowspan"));
cellToExtend.attr("rowspan", currentrowspan+1);
}
}
else{
previous = content;
cellToExtend = jthis;
}
});
};
mergeCommonCells($("#tableId"), 1);
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

Sum total for column in jQuery

The following code isn't working. I need to sum all by column as you can see on jsfiddle. What's going wrong?
HTML
<table id="sum_table" width="300" border="1">
<tr>
<td>Apple</td>
<td>Orange</td>
<td>Watermelon</td>
</tr>
<tr>
<td class="rowDataSd">1</td>
<td class="rowDataSd">2</td>
<td class="rowDataSd">3</td>
</tr>
<tr>
<td class="rowDataSd">1</td>
<td class="rowDataSd">2</td>
<td class="rowDataSd">3</td>
</tr>
<tr>
<td class="rowDataSd">1</td>
<td class="rowDataSd">2</td>
<td class="rowDataSd">3</td>
</tr>
<tr class="totalColumn">
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
</tr>
</table>
Javascript
$(document).ready(function(){
$(".rowDataSd").each(function() {
newSum.call(this);
});
});
function newSum() {
var $table = $(this).closest('table');
var total = 0;
$(this).attr('class').match(/(\d+)/)[1];
$table.find('tr:not(.totalColumn) .rowDataSd').each(function() {
total += parseInt($(this).html());
});
$table.find('.totalColumn td:nth-child('')').html(total);
}
Here is a jsffile. hope this helps
<table id="sum_table" width="300" border="1">
<tr class="titlerow">
<td>Apple</td>
<td>Orange</td>
<td>Watermelon</td>
</tr>
<tr>
<td class="rowDataSd">1</td>
<td class="rowDataSd">2</td>
<td class="rowDataSd">3</td>
</tr>
<tr>
<td class="rowDataSd">1</td>
<td class="rowDataSd">2</td>
<td class="rowDataSd">3</td>
</tr>
<tr>
<td class="rowDataSd">1</td>
<td class="rowDataSd">5</td>
<td class="rowDataSd">3</td>
</tr>
<tr class="totalColumn">
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
</tr>
</table>
<script>
var totals=[0,0,0];
$(document).ready(function(){
var $dataRows=$("#sum_table tr:not('.totalColumn, .titlerow')");
$dataRows.each(function() {
$(this).find('.rowDataSd').each(function(i){
totals[i]+=parseInt( $(this).html());
});
});
$("#sum_table td.totalCol").each(function(i){
$(this).html("total:"+totals[i]);
});
});
</script>
jsFiddle with example
To achieve this, we can take full advantage of the thead and tfoot tags within the table element. With minor changes, we have the following:
HTML
<table id="sum_table" width="300" border="1">
<thead>
<tr>
<th>Apple</th>
<th>Orange</th>
<th>Watermelon</th>
</tr>
</thead>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tfoot>
<tr>
<td>Total:</td>
<td>Total:</td>
<td>Total:</td>
</tr>
</tfoot>
</table>​​​​​​​​​​​​​​​
This then allows us to target more specifically the elements we want, i.e. how many columns are there, and what is the "total" cell.
JavaScript
$(document).ready(function()
{
$('table thead th').each(function(i)
{
calculateColumn(i);
});
});
function calculateColumn(index)
{
var total = 0;
$('table tr').each(function()
{
var value = parseInt($('td', this).eq(index).text());
if (!isNaN(value))
{
total += value;
}
});
$('table tfoot td').eq(index).text('Total: ' + total);
}​
$('#sum_table tr:first td').each(function(){
var $td = $(this);
var colTotal = 0;
$('#sum_table tr:not(:first,.totalColumn)').each(function(){
colTotal += parseInt($(this).children().eq($td.index()).html(),10);
});
$('#sum_table tr.totalColumn').children().eq($td.index()).html('Total: ' + colTotal);
});
Live example: http://jsfiddle.net/unKDk/7/
An alternate way:
$(document).ready(function(){
for (i=0;i<$('#sum_table tr:eq(0) td').length;i++) {
var total = 0;
$('td.rowDataSd:eq(' + i + ')', 'tr').each(function(i) {
total = total + parseInt($(this).text());
});
$('#sum_table tr:last td').eq(i).text(total);
}
});
Example: http://jsfiddle.net/lucuma/unKDk/10/
This is easily accomplished with a little tweaking of the classes on your table:
HTML:
<table id="sum_table" width="300" border="1">
<tr>
<td>Apple</td>
<td>Orange</td>
<td>Watermelon</td>
</tr>
<tr>
<td class="col1">1</td>
<td class="col2">2</td>
<td class="col3">3</td>
</tr>
<tr>
<td class="col1">1</td>
<td class="col2">2</td>
<td class="col3">3</td>
</tr>
<tr>
<td class="col1">1</td>
<td class="col2">2</td>
<td class="col3">3</td>
</tr>
<tr>
<td class="total">Total:</td>
<td class="total">Total:</td>
<td class="total">Total:</td>
</tr>
</table>​
JS:
var getSum = function (colNumber) {
var sum = 0;
var selector = '.col' + colNumber;
$('#sum_table').find(selector).each(function (index, element) {
sum += parseInt($(element).text());
});
return sum;
};
$('#sum_table').find('.total').each(function (index, element) {
$(this).text('Total: ' + getSum(index + 1));
});
http://jsfiddle.net/unKDk/9/
I know this has been well answered by now, but I started working on this solution earlier before all the answers came through and wanted to go ahead and post it.
This solution works with the HTML as you posted it, and assumes 4 things: 1) the first row is the header row, 2) the last row is the totals row, 3) each row has equal columns, and 4) the columns contain integers. In this case, only the table needs to be identified.
$(document).ready(function(){
totalRows("#sum_table");
});
function totalRows(tableSelector) {
var table = $(tableSelector);
var rows = table.find("tr");
var val, totals = [];
//loop through the rows getting values in the rowDataSd columns
rows
.each(function(rIndex) {
if (rIndex > 0 && rIndex < (rows.length-1)) { //not first or last row
//loop through the columns
$(this).find("td").each(function(cIndex) {
val = parseInt($(this).html());
(totals.length>cIndex) ? totals[cIndex]+=val : totals.push(val);
});
}
})
.last().find("td").each(function(index) {
val = (totals.length>index) ? totals[index] : 0;
$(this).html( "Total: " + val );
});
}
​
​
Here you go sir! http://jsfiddle.net/47VDK/

Categories

Resources