javascript: NaN when getting average - javascript

So I followed this fiddle: http://jsfiddle.net/4h6w64d8/2/
but unfortunately when I tried the code the average is NaN.
In the fiddle even though a column has no value it will still calculate and display the average. However when I tried it, it will only display NaN.
This is my html:
<table id="scorecard_student" class="table table-striped table-bordered">
<thead>
<tr>
<th>Code </th>
<th>PO 1</th>
<th>PO 2</th>
<th>PO 3</th>
<th>PO 4</th>
<th>PO 5</th>
<th>PO 6</th>
<th>PO 7</th>
<th>PO 8</th>
<th>PO 9</th>
</tr>
</thead>
<tbody>
<tr>
<td width="7%">ICT117</td>
<td></td>
<td></td>
<td></td>
<td>2.0</td>
<td></td>
<td>2.0</td>
<td></td>
<td></td>
<td>1.5</td>
</tr>
<tr>
<td width="7%">ICT118</td>
<td></td>
<td></td>
<td>2.0</td>
<td>2.0</td>
<td></td>
<td></td>
<td></td>
<td>2.0</td>
<td>1.5</td>
</tr>
<tr>
<td width="7%">ICT110</td>
<td>3.0</td>
<td>2.0</td>
<td></td>
<td></td>
<td></td>
<td>2.0</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td width="7%">ICT111</td>
<td></td>
<td></td>
<td></td>
<td>2.0</td>
<td>2.0</td>
<td>2.0</td>
<td>1.5</td>
<td></td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr bgcolor="#FFF380">
<td>
<center>Average</center>
</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
My js:
<script type="text/javascript">
var table = document.getElementById('scorecard_student'),
rows = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr'),
footer = table.getElementsByTagName('tfoot')[0];
for (var i = 1; i <= <? php echo $po_count; ?> ; i++) {
var sum = numOfValues = 0;
for (var j = 0, l = rows.length; j < l; j++) {
try {
sum += parseFloat(
rows[j].getElementsByTagName('td')[i]
.innerHTML
);
numOfValues++;
} catch (e) {}
}
var avg = sum / numOfValues;
footer.getElementsByTagName('td')[i]
.innerHTML = Math.round(avg * 100) / 100;
}
</script>
Update, I think I got it now.
if (rows[j].getElementsByTagName('td')[i].innerHTML != '') {
sum += parseFloat(
rows[j].getElementsByTagName('td')[i]
.innerHTML
) || 0;
numOfValues++;
}

In some cases you get blank text, you need to skip it:
sum += parseFloat(
rows[j].getElementsByTagName('td')[i]
.innerHTML
) || 0; //<--

Related

Getting the count of unique values for elements with regex in datatable

I have a data table that has a structure like:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers0">12345</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers1">12345</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers2">4566</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers3">12345</td>
<td></td>
</tr>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers4">2566</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers5">4566"</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers6">12345</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers7">12345</td>
<td></td>
</tr>
</tbody>
</table>
I want to have the count of the unique values present in the elements with id starting from "invNumbers".
Duplicate values should be only counted once. So here the output should be
Count = 3 . As I have only 3 unique values i.e. 12345,4566,2566.
Here are 3 versions
ES6 with fat arrows
ES2015 with function
Legacy JS which should run from IE8 or so
const uniqueCount = [...document.querySelectorAll("td[id^=invNumbers]")]
.reduce((acc, cur) => {
const val = cur.textContent;
if (!acc.includes(val)) acc.push(val);
return acc;
}, []).length;
console.log(uniqueCount)
// no fat arrows =>
const uniqueCount1 = [...document.querySelectorAll("td[id^=invNumbers]")]
.reduce(function(acc, cur) {
const val = cur.textContent;
if (!acc.includes(val)) acc.push(val);
return acc;
}, []).length;
console.log(uniqueCount1)
// Legacy - not ES2015 or ES6
var cells = document.querySelectorAll("td[id^=invNumbers]"); // supported since IE9 or so
var arr = [];
for (var i = 0; i < cells.length; i++) {
var val = cells[i].innerText;
if (arr.indexOf(val) ===-1) arr.push(val);
}
console.log(arr.length)
<table>
<tbody>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers0">12345</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers1">12345</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers2">4566</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers3">12345</td>
<td></td>
</tr>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers4">2566</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers5">4566</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers6">12345</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers7">12345</td>
<td></td>
</tr>
</tbody>
</table>
You could try something like this:
var arr = $('td[id^=invNumbers]').map(function() {
return $(this).text()
}).get();
var unique = arr.filter(function(v, i, a) {
return a.indexOf(v) === i
});
Demo
var arr = $('td[id^=invNumbers]').map(function() {
return $(this).text()
}).get();
var unique = arr.filter(function(v, i, a) {
return a.indexOf(v) === i
});
console.log(unique);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers0">12345</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers1">12345</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers2">4566</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers3">12345</td>
<td></td>
</tr>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers4">2566</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers5">4566</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers6">12345</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers7">12345</td>
<td></td>
</tr>
</tbody>
</table>

Jquery or Javascript create ranking column based from total

I want to compute and fill the ranking in the image below based on the total. How will be able to achieve this using js/jquery?.
I have created the table manually (dynamically also) using HTML. I also have button to generate the rank (which I know how to do it). I just want to have a function or way to add rank to my column.
So that rank should be in order (1, 2, 2, 3).
<table id="table" class="table table-stripe table-bordered">
<thead>
<tr>
<td class="d-none">ID</td>
<td>Name</td>
<td>Crit1</td>
<td>Crit2</td>
<td>Crit3</td>
<td>Crit4</td>
<td>Crit5</td>
<td>Total</td>
<td>Rank</td>
</tr>
</thead>
<tbody>
<tr>
<td class="d-none">2</td>
<td>aaaa</td>
<td>20</td>
<td>0</td>
<td>50</td>
<td>0</td>
<td>0</td>
<td class="total"></td>
<td class="Rank"></td>
</tr>
<tr>
<td class="d-none">3</td>
<td>Greggggg</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="total"></td>
<td class="Rank"></td>
</tr>
<tr>
<td class="d-none">4</td>
<td>Jjjjoohhn</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="total"></td>
<td class="Rank"></td>
</tr>
<tr>
<td class="d-none">5</td>
<td>asdada</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="total"></td>
<td class="Rank"></td>
</tr>
</tbody>
</table>
Any help will be appreciated.
You have to organise the total score by getting all the values, sort and remove duplicates.
And you can assign the rank value by $('.total').filter(function() {return $(this).text() == v;}).next().text(i + 1);
You can do something like:
$(function() {
//Get all total values, sort and remove duplicates
let totalList = $(".total")
.map(function() {return $(this).text()})
.get()
.sort(function(a,b){return a - b })
.reduce(function(a, b) {if (b != a[0]) a.unshift(b);return a}, [])
//Assign rank
totalList.forEach((v, i) => {
$('.total').filter(function() {return $(this).text() == v;}).next().text(i + 1);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table" class="table table-stripe table-bordered">
<thead>
<tr>
<td class="d-none">ID</td>
<td>Name</td>
<td>Crit1</td>
<td>Crit2</td>
<td>Crit3</td>
<td>Crit4</td>
<td>Crit5</td>
<td>Total</td>
<td>Rank</td>
</tr>
</thead>
<tbody>
<tr>
<td class="d-none">2</td>
<td>aaaa</td>
<td>20</td>
<td>0</td>
<td>50</td>
<td>0</td>
<td>0</td>
<td class="total">80</td>
<td class="Rank"></td>
</tr>
<tr>
<td class="d-none">3</td>
<td>Greggggg</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="total">65</td>
<td class="Rank"></td>
</tr>
<tr>
<td class="d-none">4</td>
<td>Jjjjoohhn</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="total">65</td>
<td class="Rank"></td>
</tr>
<tr>
<td class="d-none">5</td>
<td>asdada</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="total">50</td>
<td class="Rank"></td>
</tr>
</tbody>
</table>
You can even make it shorter like
$(".total")
.map(function(){return $(this).text()})
.get()
.sort(function(a,b){return a - b })
.reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
.forEach((v,i)=>{
$('.total').filter(function() {return $(this).text() == v;}).next().text(i + 1);
});

How to find the sum of dynamically generated multiple table columns

I have table with some data in an array to be displayed as below. In this example, I display 2 table datas but it can be more than 2. I have to calculate the column population, collection 1 and collection 2 of each table and show then at the end of each table.
So far I have tried following code to calculate where I first calcuate the number of tables available by counting array.
<script type="text/javascript">
var count = <?php echo json_encode(count($lists)); ?>;
var total = 0;
for(var i = 1; i <= count; i++)
{
var available = $(".used-community .plant_counter_"+i);
$.each(available, function(key, value)
{
total+=parseInt(available[key].innerText);
});
console.log(total);//edit variable name - totala changed to total
}
</script>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="47" class="rowList middle">
<td>Wangkha</td>
<td>Soi Wangkha 3</td>
<td class="plant_counter_1">100000</td>
<td>31</td>
<td>11315</td>
</tr>
<tr id="43" class="rowList middle">
<td>one</td>
<td>one address</td>
<td class="plant_counter_1">35000</td>
<td>7</td>
<td>2555</td>
</tr>
<tr id="46" class="rowList middle">
<td>Bang</td>
<td>Bang khuwang Rd</td>
<td class="plant_counter_1">6000</td>
<td>2</td>
<td>730</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="45" class="rowList middle">
<td>sap</td>
<td>sap thawi</td>
<td class="plant_counter_2">80000</td>
<td>15</td>
<td>5475</td>
</tr>
<tr id="44" class="rowList middle">
<td>two-nonthaburi</td>
<td>nonthaburi</td>
<td class="plant_counter_2">69000</td>
<td>11</td>
<td>4015</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
My code is calculating the row with class "plant_counter_1" correctly but for next table it continue adding the sum of table 1 as well. Can anybody teach me where I did mistake and I how can I find out the sum of other two columns
Thank You
Loop over each table and work within that table instance. The total data count is not really needed since it doesn't break down the number of tables.
Since you can easily isolate table instances I would suggest you use common class names across all tables and don't use incremental ones
$('table').each(function(){
var $table =$(this),
$rows = $table.find('tbody tr'),
$lastRowCells = $rows.last().children(),
collectionTotals = $rows.not(':last').map(function(){
var $cells = $(this).children()
return [[+$cells[3].textContent, +$cells[4].textContent]]
}).get()
.reduce(function(a,c){
$.each(c,function(i, val){
a[i] += val;
});
return a;
},[0,0]);
$lastRowCells.eq(3).text(collectionTotals[0]);
$lastRowCells.eq(4).text(collectionTotals[1]);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="47" class="rowList middle">
<td>Wangkha</td>
<td>Soi Wangkha 3</td>
<td class="plant_counter">100000</td>
<td>31</td>
<td>11315</td>
</tr>
<tr id="43" class="rowList middle">
<td>one</td>
<td>one address</td>
<td class="plant_counter">35000</td>
<td>7</td>
<td>2555</td>
</tr>
<tr id="46" class="rowList middle">
<td>Bang</td>
<td>Bang khuwang Rd</td>
<td class="plant_counter">6000</td>
<td>2</td>
<td>730</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="45" class="rowList middle">
<td>sap</td>
<td>sap thawi</td>
<td class="plant_counter">80000</td>
<td>15</td>
<td>5475</td>
</tr>
<tr id="44" class="rowList middle">
<td>two-nonthaburi</td>
<td>nonthaburi</td>
<td class="plant_counter">69000</td>
<td>11</td>
<td>4015</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Just a small modification to your code and it will work. Since you need multiple results, your total needs to be an array. Please run attached code snippet for clarity.
var count =2;//change back to your php <?php echo json_encode(count($lists)); ?>;
var total = new Array();
total.push(0);
for(var i = 1; i <= count; i++)
{
total.push(0);
var available = $(".used-community .plant_counter_"+i);
$.each(available, function(key, value)
{
total[i]+=parseInt(available[key].innerText);
});
total.push(0);
console.log(total[i]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="47" class="rowList middle">
<td>Wangkha</td>
<td>Soi Wangkha 3</td>
<td class="plant_counter_1">100000</td>
<td>31</td>
<td>11315</td>
</tr>
<tr id="43" class="rowList middle">
<td>one</td>
<td>one address</td>
<td class="plant_counter_1">35000</td>
<td>7</td>
<td>2555</td>
</tr>
<tr id="46" class="rowList middle">
<td>Bang</td>
<td>Bang khuwang Rd</td>
<td class="plant_counter_1">6000</td>
<td>2</td>
<td>730</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="45" class="rowList middle">
<td>sap</td>
<td>sap thawi</td>
<td class="plant_counter_2">80000</td>
<td>15</td>
<td>5475</td>
</tr>
<tr id="44" class="rowList middle">
<td>two-nonthaburi</td>
<td>nonthaburi</td>
<td class="plant_counter_2">69000</td>
<td>11</td>
<td>4015</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
to make things a little bit of fun
(I assumed the total rows have two extra misplaced columns)
;$(function() {
var tables = $('table > tbody');
var totals = new Array(tables.length);
tables.each(function(nt,t) {
var rows = $('tr',t);
var totalElement = rows.splice(-1);
rows = rows.map(function(nr, r) {
return [$('td',$(r)).slice(-3)
.map( function(nc,c) {
return parseInt($(c).text()) || 0; }).toArray()];
}).toArray();
totals[nt] = rows.reduce( function(a, b) {
return a.map(function(v,n) { return v + b[n]; });
}, [0,0,0] );
$('td',totalElement[0]).splice(-3).forEach(function(c,n) {
$(c).text(totals[nt][n]); });
});
console.log(totals);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="47" class="rowList middle">
<td>Wangkha</td>
<td>Soi Wangkha 3</td>
<td class="plant_counter_1">100000</td>
<td>31</td>
<td>11315</td>
</tr>
<tr id="43" class="rowList middle">
<td>one</td>
<td>one address</td>
<td class="plant_counter_1">35000</td>
<td>7</td>
<td>2555</td>
</tr>
<tr id="46" class="rowList middle">
<td>Bang</td>
<td>Bang khuwang Rd</td>
<td class="plant_counter_1">6000</td>
<td>2</td>
<td>730</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
</tr>
</tbody>
</table>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="45" class="rowList middle">
<td>sap</td>
<td>sap thawi</td>
<td class="plant_counter_2">80000</td>
<td>15</td>
<td>5475</td>
</tr>
<tr id="44" class="rowList middle">
<td>two-nonthaburi</td>
<td>nonthaburi</td>
<td class="plant_counter_2">69000</td>
<td>11</td>
<td>4015</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
</tr>
</tbody>
</table>
Well if I understand you correctly. You can store the total sum of each table into array. I think the code explain alone... But I declare an array named
'total' outside of the for statement that contain the total of each table. When the foreach finish to sum all the values in tempTotal, then do a push to total array and save the operation of the first loop. and the second... third... etc
var total = [];
for(var i = 1; i <= 2; i++)
{
var tempTotal = 0;
var available = $(".used-community .plant_counter_"+i);
$.each(available, function(key, value)
{
tempTotal = tempTotal + parseInt(available[key].innerText);
});
total.push(tempTotal);
}
console.log(total);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="47" class="rowList middle">
<td>Wangkha</td>
<td>Soi Wangkha 3</td>
<td class="plant_counter_1">100000</td>
<td>31</td>
<td>11315</td>
</tr>
<tr id="43" class="rowList middle">
<td>one</td>
<td>one address</td>
<td class="plant_counter_1">35000</td>
<td>7</td>
<td>2555</td>
</tr>
<tr id="46" class="rowList middle">
<td>Bang</td>
<td>Bang khuwang Rd</td>
<td class="plant_counter_1">6000</td>
<td>2</td>
<td>730</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table class="table" border="1">
<thead>
<tr class="titlerow">
<th>Name</th>
<th>Address</th>
<th>Population</th>
<th>Collection 1</th>
<th>collection 2</th>
</tr>
</thead>
<tbody class="used-community">
<tr id="45" class="rowList middle">
<td>sap</td>
<td>sap thawi</td>
<td class="plant_counter_2">80000</td>
<td>15</td>
<td>5475</td>
</tr>
<tr id="44" class="rowList middle">
<td>two-nonthaburi</td>
<td>nonthaburi</td>
<td class="plant_counter_2">69000</td>
<td>11</td>
<td>4015</td>
</tr>
<tr bgcolor="#66CCFF">
<td></td>
<td></td>
<td></td>
<td class="col"></td>
<td class="cap"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

how to join rows in table [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm looking for help with my project.I want to convert my HTML table
from:
A B C D E F
217 x
221 x
275 x
275 x
290 x x
to:
A B C D E F
217 x
221 x
275 x x
290 x x
In the first table there are 2 rows with number 275,How do I merge them together ?
For html table use a hashmap to track unique rows as you loop through the rows once. As duplicates are found you merge the text with stored row and remove the duplicate
var uniqueRows = {};
$('tbody tr').each(function(){
var $row = $(this),
num = $row.find('td:first').text().trim();
if(!uniqueRows[num]){
// store this row object for future text merge
uniqueRows[num] = $row
}else{
// match found, merge the text
uniqueRows[num].find('td').text(function(i, existText){
return existText ? existText : $row.find('td').eq(i).text()
});
$row.remove();
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>
</th>
<th>A
</th>
<th>B
</th>
<th>C
</th>
<th>D
</th>
<th>E
</th>
<th>F
</th>
</tr>
</thead>
<tbody>
<tr>
<td>217</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
</tr>
<tr>
<td>221</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
</tr>
<tr>
<td>275</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>275</td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>275</td>
<td></td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>290</td>
<td>x</td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Third alternative - saving the content and rewriting
$(function() {
let cont = {};
$("table>tbody>tr").each(function(_, row) {
var key = $("td:first", row).text();
if (cont[key] == undefined) cont[key] = [];
$("td", row).each(function(i,cell) {
let text = $.trim(cell.innerText);
if (cont[key][i] == undefined || cont[key][i] =="") cont[key][i] = text;
});
});
$("table>tbody").empty();
$.each(cont,function(key,arr) {
$("table>tbody").append("<tr><td>"+arr.join("</td><td>")+"</td></tr>");
})
});
td {
border: 1px solid black
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
<th>F</th>
</tr>
</thead>
<tbody>
<tr>
<td>217</td>
<td></td>
<td></td>
<td> </td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td>221</td>
<td></td>
<td></td>
<td> </td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>275</td>
<td> </td>
<td></td>
<td>x</td>
<td> </td>
<td>x</td>
</tr>
<tr>
<td>275</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td> </td>
<td></td>
</tr>
<tr>
<td>290</td>
<td>x</td>
<td></td>
<td>x</td>
<td> </td>
<td></td>
</tr>
</tbody>
</table>
Try the following:
It will search for duplicated words in the first td in each tr. If match then it will move the content to the first tr and then remove the duplicated tr
var arr = [];
$("table tbody tr").each(function() {
arr.push($(this).find("td:first").text())
})
var sorted_arr = arr.slice().sort();
var results = [];
for (var i = 0; i < arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
$.each(results, function(i, x) {
var tr = $("table tbody tr td:contains(" + x + "):first").parent()
$(tr).nextAll("tr").find("td:contains(" + x + "):first").each(function(k, l) {
var s = $(l).parent();
$(s).children("td").each(function(t, u) {
if ($(u).text() == "x") {
var td = $(tr).find("td:eq(" + t + ")")
td.text(td.text() + $(u).text())
}
})
s.remove();
})
})
var arr = [];
$("table tbody tr").each(function() {
arr.push($(this).find("td:first").text())
})
var sorted_arr = arr.slice().sort();
var results = [];
for (var i = 0; i < arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
$.each(results, function(i, x) {
var tr = $("table tbody tr td:contains(" + x + "):first").parent()
$(tr).nextAll("tr").find("td:contains(" + x + "):first").each(function(k, l) {
var s = $(l).parent();
$(s).children("td").each(function(t, u) {
if ($(u).text() == "x") {
var td = $(tr).find("td:eq(" + t + ")")
td.text(td.text() + $(u).text())
}
})
s.remove();
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>
</th>
<th>A
</th>
<th>B
</th>
<th>C
</th>
<th>D
</th>
<th>E
</th>
<th>F
</th>
</tr>
</thead>
<tbody>
<tr>
<td>217</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
</tr>
<tr>
<td>221</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
</tr>
<tr>
<td>275</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>275</td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>275</td>
<td></td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>290</td>
<td>x</td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

Sum up table columns in a loop using javascript stuck

I have a loop where i want display tables and calculate the sum here is html
#for (int i = 0; i < 3; i++) {
<table id="table #i" class="tableSum">
<thead>
<tr>
<td>Items</td>
<td>Quantity</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>5</td>
<td>100</td>
</tr>
<tr>
<td>Organe</td>
<td>5</td>
<td>200</td>
</tr>
<tr>
<td>Banana</td>
<td>5</td>
<td>200</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
}
In javascript i wrote this code, I want the method can sum up all data in column 2 and 3 then display on the footer of each table in a loop, but when i run this code, it returned wrong sum and only display in 1st table.
$(document).ready(function () {
$('table').each(function () {
calculateColumn(1);
calculateColumn(2);
})
});
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);
}
When you say $('table tr').each(), it iterates over all the tr elements in the page, not just the one's in the current table(which is targeted by $('table').each())
You need to pass the table reference to the calculate method
$(document).ready(function() {
$('table').each(function() {
calculateColumn(this, 1);
calculateColumn(this, 2);
})
});
function calculateColumn(table, index) {
var total = 0;
$(table).find('tbody td:nth-child(' + (index + 1) + ')').each(function() {
total += +$(this).text() || 0;
});
$(table).find('tfoot td').eq(index).text(total);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="table1" class="tableSum">
<thead>
<tr>
<td>Items</td>
<td>Quantity</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>6</td>
<td>100</td>
</tr>
<tr>
<td>Organe</td>
<td>6</td>
<td>150</td>
</tr>
<tr>
<td>Banana</td>
<td>3</td>
<td>75</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
<table id="table1" class="tableSum">
<thead>
<tr>
<td>Items</td>
<td>Quantity</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>5</td>
<td>120</td>
</tr>
<tr>
<td>Organe</td>
<td>4</td>
<td>100</td>
</tr>
<tr>
<td>Banana</td>
<td>5</td>
<td>300</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
<table id="table1" class="tableSum">
<thead>
<tr>
<td>Items</td>
<td>Quantity</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>10</td>
<td>100</td>
</tr>
<tr>
<td>Organe</td>
<td>5</td>
<td>300</td>
</tr>
<tr>
<td>Banana</td>
<td>5</td>
<td>300</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>

Categories

Resources