How to create rows cell loop in js - javascript

I am trying to sum a table column total.
Here is an example of only two column for test purposes. I want to calculate table column's item total using a javascript loop.
How to create the loop if we don't know how many rows and columns are inside in table? I hope you understand what I mean and also hope for your kindly suggestion.
<p><b>Student at Stanford University 2013-2014</b></p>
<table><tr><th>Faculty (Subject)</th><th>Student 2013</th><th>Student 2014</th></tr></table>
<table id="sdtable">
<tr><th>Business</th><td>12922</td><td>11420</td></tr>
<tr><th>Earth Sciences</th><td>4320</td><td>4611</td></tr>
<tr><th>Education</th><td>14560</td><td>13490</td></tr>
<tr><th>Engineering</th><td>8750</td><td>9863</td></tr>
<tr><th>Humanities & Sciences</th><td>7819</td><td>7219</td></tr>
<tr><th>Medicine</th><td>5219</td><td>4200</td></tr>
</table>
<button onclick="Calculate()">Calculate</button>
<div id="Studentf" class="Studentf"></div>
<div id="Students" class="Students"></div>
<div id="Studentt" class="Studentt"></div>
and
var ftable = document.getElementById("sdtable");
var i= 0;
var sumFirst=0;
var sumSecond=0;
var sumTotal=0;
function Calculate(){
for (i=0;i<ftable.rows.length; i++){
sumFirst=sumFirst+parseInt(ftable.rows[i].cells[1].innerHTML);
sumSecond=sumSecond+parseInt(ftable.rows[i].cells[2].innerHTML);
}
sumTotal=sumFirst+sumSecond;
document.getElementById("Studentf").innerHTML +="<b>Student in 2013 = </b>" +sumFirst;
document.getElementById("Students").innerHTML +="<b>Student in 2014 = </b>" +sumSecond;
document.getElementById("Studentt").innerHTML +="<b>Total Student = </b>" +sumTotal;
}

The key here is that you need to use cells collection to get number of columns that can change when you add new years to the table. You will also have to dynamically create elements for summary information per year.
Here is an example:
var ftable = document.getElementById("sdtable");
var i = 0;
var sumFirst = 0;
var sumSecond = 0;
var sumTotal = 0;
function Calculate() {
var rows = ftable.tBodies[0].rows,
header = ftable.tHead.rows[0],
cells = ftable.tBodies[0].rows[0].cells,
years = [];
for (var i = 0; i < rows.length; i++) {
for (var j = 1; j < cells.length; j++) {
if (!years[j]) years[j] = 0;
years[j] += parseInt(rows[i].cells[j].innerHTML);
}
}
sumTotal = years.reduce(function(prev, curr) {
return prev + curr;
}, 0);
var sum = document.getElementById("sum");
sum.innerHTML = '';
for (var j = 1; j < cells.length; j++) {
console.log(header.cells[j])
sum.insertAdjacentHTML('afterbegin', '<p><b>' + header.cells[j].innerHTML + '</b> = ' + years[j] + '</p>');
}
sum.insertAdjacentHTML('beforeend', "<b>Total Student = </b>" + sumTotal);
}
Demo: http://jsfiddle.net/x2sscpxL/1/

The table should probably look more like:
<table>
<thead>
<tr><th>Faculty (Subject)</th><th>Student 2013</th><th>Student 2014</th></tr>
</thead>
<tbody id="sdtable">
<tr><th>Business</th><td>12922</td><td>11420</td></tr>
<tr><th>Earth Sciences</th><td>4320</td><td>4611</td></tr>
<tr><th>Education</th><td>14560</td><td>13490</td></tr>
...
</tbody>
<tfoot>
<tr><th>Totals:</th><th></th><th></th></tr>
</table>
to split the header, body and footer into separate table sections. The function should then be like:
function calculate(){
// Get a reference to the tBody
var tBody = document.getElementById('sdtable');
if (!tBody) return;
var row, rows = tBody.rows;
var cell, cells;
var cellTotals = {};
// For each row in the body
for (i=0, iLen=rows.length; i<iLen; i++) {
row = rows[i];
cells = row.cells;
// Add the cells in each column, starting on the second column
// i.e. starting with cell index 1
for (var j=1, jLen=cells.length; j<jLen; j++) {
cell = cells[j];
if (j in cellTotals) {
cellTotals[j] += Number(cell.textContent || cell.innerText);
} else {
cellTotals[j] = Number(cell.innerHTML);
}
}
}
// Write the totals into the footer
var tFoot = tBody.parentNode.tFoot;
row = tFoot.rows[0];
for (var k=1; k<jLen; k++) {
row.cells[k].innerHTML = cellTotals[k];
}
}
Note that by convention, variables with a name starting with a capital letter are reserved for constructors (though constants usually are all caps).

Here is calculation of table witn n rows and n columns
Note: header cells wrapped in thead section
var ftable = document.getElementById("sdtable");
var tbody = ftable.getElementsByTagName("tbody")[0]
var columnsCount = ftable.rows[0].cells.length;
var sumTotal = [];
for(i=0; i<columnsCount;i++)
sumTotal.push(0); //here initialize with zero
function Calculate(){
for (i=0;i<tbody.rows.length; i++){
for (j=0; j<columnsCount; j++)
if (tbody.rows[i].cells[j] && tbody.rows[i].cells[j].innerHTML)
sumTotal[j] += parseInt(tbody.rows[i].cells[j].innerHTML);
}
return sumTotal;
}
sumTotal = Calculate();
tfootrow = ftable.tFoot.rows[0];
console.log(tfootrow)
for(i=0; i<sumTotal.length; i++){
tfootrow.insertCell(i).innerHTML = sumTotal[i];
}
<table id="sdtable">
<thead>
<tr>
<th>Business</th>
<th>Earth Sciences</th>
<th>Education</th>
<th>Engineering</th>
<th>Humanities & Sciences</th>
<th>Medicine</th>
</tr>
</thead>
<tbody>
<tr><td>12922</td><td>11420</td></tr>
<tr><td>4320</td><td>4611</td></tr>
<tr><td>14560</td><td>13490</td></tr>
<tr><td>8750</td><td>9863</td></tr>
<tr><td>7819</td><td>7219</td></tr>
<tr><td>5219</td><td>4200</td></tr>
<tr><td></td><td>1</td><td>2</td></tr>
</tbody>
<tfoot>
<tr></tr>
</tfoot>
</table>

Related

javascript dynamic table filling

I have multiple arrays lets say:
var animals = ["cow","horse","rabbit","elephant","donkey","monkey","zebra"];
var food = ["apple","banana","pear","melon","grape","peach","pineapple"];
I want to put this in 4-column table dynamically. if click on animals picture the animals array would fill the table, if food, then food array would fill the table.
So, lets say I have
<table class="myTable"></table>
Then need javascript
import $ from "https://cdn.skypack.dev/jquery#3.6.1";
var animals = ["cow","horse","rabbit","elephant","donkey","monkey","zebra"];
var food = ["apple","banana","pear","melon","grape","peach","pineapple"];
var $table = $('.myTable');
for (var i = 0; i < food.length; i++){
var $aSingleContent = '<tr><td>'+food[i]+'</td></tr>';
$table.append($aSingleContent);
}
This would display all food items in 1 column. Now I need to divide this by 4 - because 4 columns in a row
because of <tr> in line var $aSingleContent = '<tr><td>'+food[i]+'</td></tr>'; makes your javascript create a new row for every element in array. we need to keep count the amount of data that had filled a row. if a row has 4 columns columnCount === 4, then we create a new row.
const food = ["apple","banana","pear","melon","grape","peach","pineapple"];
const $table = $('.myTable');
let $aSingleContent = "<tr>", columnCount = 0;
for (var i = 0; i < food.length; i++){
if(columnCount === 4) {
columnCount = 0;
$aSingleContent += '</tr><tr>';
}
$aSingleContent += '<td>'+food[i]+'</td>';
columnCount++;
}
$aSingleContent += "</tr>"
$table.append($aSingleContent);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="myTable" border></table>
You can try this:
window.onload = function() {
var animals = ["cow","horse","rabbit","elephant","donkey","monkey","zebra"];
var food = ["apple","banana","pear","melon","grape","peach","pineapple"];
var table = document.getElementById("table");
var i = 0, r = 0;
while(i < animals.length) {
var row = table.insertRow(r);
for (var c = 0; c < 4; c++) {
var cell = row.insertCell(c);
cell.appendChild(document.createTextNode(animals[i] ? animals[i] : ''));
i++;
}
r++;
}
document.body.appendChild(table);
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table" cellpadding="1" cellspacing="1">
</table>
Hope this help!
If you have food array more than you provide you can use this one.
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.1.slim.min.js" integrity="sha256-w8CvhFs7iHNVUtnSP0YKEg00p9Ih13rlL9zGqvLdePA=" crossorigin="anonymous"></script>
</head>
<body>
<table class="myTable" border="1">
</table>
<script>
var animals = ["cow","horse","rabbit","elephant","donkey","monkey","zebra"];
var food = ["apple","banana","pear","melon","grape","peach","pineapple", "a","b","c","d"];
var $table = $('.myTable');
var $aSingleContent = '';
var to = 0;
var from = 3;
for (var i = 0; i < food.length; i++){
if (i==to)
{ $aSingleContent += '<tr>'; }
$aSingleContent += '<td>'+food[i]+'</td>';
if (i==from)
{
$aSingleContent += '</tr>';
to = to + 4;
from = from + 4;
}
}
$table.append($aSingleContent);
</script>
</body>
</html>

Vanilla javascript update a table if a button is clicked

I am trying to update a table once a button is clicked. I have created the table and the button with the following HTML code
<button type="button" onclick="calculateMatrixFact()">Calculate MF!</button>
<table id = "matrix_factorization">
<tr>
<th>User</th>
<th>Movie One</th>
<th>Movie Two</th>
</tr>
</table>
While the function that I am calling on the onclick event, is the following:
function calculateMatrixFact(){
var cache = CacheValues();
// split the array in two single arrays one per each user and movie
var user_matrix = createGroups(cache.mu, 2);
var score_matrix = createGroups(cache.ms, 2);
// remove the string user_name and movie_name
for (let i = 0; i < user_matrix.length && i < score_matrix.length; i++) {
user_matrix[i].shift();
score_matrix[i].shift();
}
var dot_matrix = [];
// perform the dot product
for (let j = 0; j < user_matrix.length; j++) {
for (let k = 0; k < score_matrix.length; k++) {
//console.log(user_matrix[j])
//console.log(score_matrix[k])
var dot_product = math.multiply(user_matrix[j], score_matrix[k]);
dot_matrix.push(dot_product);
}
}
// create the matrix and push back the string (first column of the table)
var dot_prod_matrix = createGroups(dot_matrix, 2);
dot_prod_matrix[0].unshift("Anna");
dot_prod_matrix[1].unshift("Jonny");
// from array to HTML table
fetch = document.getElementById('matrix_factorization');
for (var i = 0; i < dot_prod_matrix.length; i++) {
var newRow = fetch.insertRow(fetch.length);
for (var j = 0; j < dot_prod_matrix[i].length; j++) {
var cell = newRow.insertCell(j);
cell.innerHTML = dot_prod_matrix[i][j];
}
}
}
I think the problem is that I do not reset the table each time the button is clicked, is that right? How can I delete the old info and insert the new ones?
Here you can see the full code: https://jsfiddle.net/932ebu0v/7/
Because of this block in very last of your function:
fetch = document.getElementById('matrix_factorization');
for (var i = 0; i < dot_prod_matrix.length; i++) {
var newRow = fetch.insertRow(fetch.length);
for (var j = 0; j < dot_prod_matrix[i].length; j++) {
var cell = newRow.insertCell(j);
cell.innerHTML = dot_prod_matrix[i][j];
}
}
The fetch will get the existing table that having rows and you just inserting new rows into it.
Then, you can just clear whole table, re-add the header and insert the row (the clear and re-instantiation of the header would be done in one line of code !!):
fetch = document.getElementById('matrix_factorization');
// Just use this line to clear whole table and put back the header row
fetch.innerHTML = `<tr>
<th>User</th>
<th>Movie One</th>
<th>Movie Two</th>
</tr>`; // Put your whole <th> here.
// as for the rest, just let it be
for (var i = 0; i < dot_prod_matrix.length; i++) {
var newRow = fetch.insertRow(fetch.length);
for (var j = 0; j < dot_prod_matrix[i].length; j++) {
var cell = newRow.insertCell(j);
cell.innerHTML = dot_prod_matrix[i][j];
}
}
A simple solution would be to keep the 1st row in the <thead> element, given that it functions as the table's header. The rest of the rows go inside the <tbody> element. Only the table body is reset each time the button is clicked.
// access tbody (thead remains unimpacted)
var mfTableBody = document.querySelector('#matrix_factorization tbody');
mfTableBody.innerHTML = ''; // clear tbody
for (var i = 0; i < dot_prod_matrix.length; i++) {
// insert tr inside tbody
var newRow = mfTableBody.insertRow(fetch.length);
for (var j = 0; j < dot_prod_matrix[i].length; j++) {
var cell = newRow.insertCell(j);
cell.innerHTML = dot_prod_matrix[i][j];
}
}
<table id="matrix_factorization">
<thead>
<tr>
<th>User</th>
<th>Movie One</th>
<th>Movie Two</th>
</tr>
</thead>
<tbody></tbody>
</table>

JavaScript: dynamic delete row operation error

I am trying on following code;
Why doesn't deleteRow() alert "hi" when we click on delete button for first time (nor it delete row)?
Surprisingly it will work perfectly second time.
HTML
<div style="height: 190px;overflow: auto;left:220px;width:710px;" id="filterTable">
<table id="filterTableBody" style="border-collapse: collapse; border: 1px solid black;width:690px;" border="1">
<tbody><tr bgcolor="#FF6600">
<td><strong>
and/or
</strong></td>
<td><strong>
Column Name
</strong></td>
<td><strong>
operator
</strong></td>
<td><strong>
Filter
</strong></td>
<td><strong>
Delete
</strong></td>
</tr>
<tr><td> </td><td>WORKGROUP_NAME</td><td>!=</td><td>ABDEL HAMEID</td><td><img src="/images/delete.gif"></td></tr></tbody></table>
</div>
Javascript
function deleteRow(){
var table = document.getElementById('filterTableBody');
var rows1 = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
for (var i = 0; i < rows1.length; i++) {
rows1[i].onclick = (function() {
alert("hi");
table.deleteRow(this.rowIndex);
var oTable = document.getElementById('filterTableBody');
//gets rows of table
var rowLength = oTable.rows.length;
for (i = 1; i < rowLength; i++){
var oCells = oTable.rows.item(i).cells;
//gets cells of current row
var cellLength = oCells.length-1;
for(var j = 0; j < cellLength; j++){
oCells.item(j).innerHTML = "";
break;
}
break;
}
});
}
}
Why doesn't the code run in first click and why it runs in the second?
The reason is because the onclick event handler for the rows are getting attached only when the Delete button is clicked for the first time.
They have to be attached onload itself. You can do it like below:
window.onload = deleteRow;
Demo Fiddle
This code works for me. Thank you #harry for pin pointing the problem.
function deleteRowUI(btndel) {
var table=document.getElementById('filterTableBody');
if (typeof(btndel) == "object") {
p=btndel.parentNode.parentNode;
p.parentNode.removeChild(p);
var oTable = document.getElementById('filterTableBody');
//gets rows of table
var rowLength = oTable.rows.length;
for (var i = 1; i < rowLength; i++){
var oCells = oTable.rows.item(i).cells;
//gets cells of current row
var cellLength = oCells.length-1;
for(var j = 0; j < cellLength; j++){
oCells.item(j).innerHTML = "";
break;
}
break;
}
} else {
return false;
}
}

Separate rows and columns while creating 2d dynamic table

I can't separate row and column td's as I create a 2d table with jquery..
How do I create 10 rows 10 columns 2d table:
what I have done so far:
$(document).ready(function () {
for (var i = 1; i <= 10; i++) {
$('.box').append('<td/>' + '</p>');
for (var j = 1; j <= 10; j++); {
$('.box').append('<td/>');
}
}
});
http://jsfiddle.net/VS37n/
thnx in advance!
You want a table that has 10 columns and 10 rows.
var rows = 10;
var cols = 10;
In an HTML table structure, rows come first in the hierarchy, so, create those first:
$(document).ready(function() {
var rows = 10;
var cols = 10;
var box = $('.box');
for (var r = 0; r < rows; r++) {
var tr = $('<tr>');
//Here we will append the columns to the row before appending it to the box.
box.append(tr);
}
});
The above code only makes 10 rows for us. Now we need to add 10 columns to each row:
$(document).ready(function() {
var rows = 10;
var cols = 10;
var box = $('.box');
for (var r = 0; r < rows; r++) {
var tr = $('<tr>');
for (var c = 0; c < cols; c++) {
tr.append($('<td><p></p></td>')); //Create the table cell, with a p element as in your example, and append it to the row.
}
box.append(tr);
}
});
See this FIDDLE
UPDATE
I just noticed that the jQuery selector from your post selects the <div> element with class .box. You want to add these rows and columns, however, to a <table> element, which doesn't exist. I'd suggest you add a <table> element into your HTML, or, add it with Javascript before adding the rows.
If you can add a <table> element inside of your .box div, then you would just change the following line:
var box = $('.box');
to:
var box = $('.box table:first');
If you can't change the HTML for some reason, then you can dynamically create the table before the rows and columns:
var box = $('<table>').appendTo('.box');
Is this what you're trying to do?
$(document).ready(function () {
var tdHtml = "":
var trHtml = "";
var tableHtml = "";
for(var i=1;i<=10;i++)
{
tdHtml += "<td></td>";
}
for(var j=1;j<=10;j++);
{
trHtml += ("<tr>" + tdHtml + "</tr>");
}
tableHtml = ("<table>" + trHtml + "</table>");
$('.box').innerHtml(tableHtml);
});
You had a ; after your for loop :
for (var j = 1; j <= 10; j++); {
$('.box').append('<td/>');
}
Furthermore, you are not adding <tr> elements.
See the updated fiddle

Combine HTML Table Rows with Javascript

Is there an easy way to combine rows in an HTML table where the first column is the same? I basically have a table set up like:
<table>
<tr><td>test</td><td>12345</td><td>12345</td><tr>
<tr><td>test</td><td>12345</td><td>12345</td><tr>
<tr><td>test2</td><td>12345</td><td>12345</td><tr>
<tr><td>test</td><td>12345</td><td>12345</td><tr>
<tr><td>test2</td><td>12345</td><td>12345</td><tr>
</table>
and I want it to generate:
<table>
<tr><td>test</td><td>37035</td><td>37035</td><tr>
<tr><td>test2</td><td>24690</td><td>24690</td><tr>
</table>
using jQuery:
var map = {};
$('table tr').each(function(){
var $tr = $(this),
cells = $tr.find('td'),
mapTxt = cells.eq(0).text();
if(!map[mapTxt]){
map[mapTxt] = cells;
} else {
for(var i=1, l=cells.length; i<l; i++){
var cell = map[mapTxt].eq(i);
cell.text(parseInt(cell.text()) + parseInt(cells[i].text()));
}
$tr.remove();
}
});
this is a "dumb" script -- no error handling for cases like different number of cells, fields being non-numeric, etc. Add those if necessary.
Also, depending on how it's generated, it's better to do this server-side.
Here's a plain JavaScript version.
window.onload = function() {
var table = document.getElementById('mytable');
var tr = table.getElementsByTagName('tr');
var combined = Array();
for (i = 0; i < tr.length; i++) {
var td = tr[i].getElementsByTagName('td');
var key = td[0].innerText;
if (!combined[key]) {//if not initialised
combined[key] = Array();
for (j = 0; j < td.length - 1; j++) combined[key][j] = 0;
}
for (j = 0; j < td.length - 1; j++)
combined[key][j] += parseInt(td[j + 1].innerText);
}
while (table.hasChildNodes()) table.removeChild(table.lastChild);
var tbody = document.createElement('tbody');//needed for IE
table.appendChild(tbody);
for (var i in combined) {
tr = document.createElement('tr');
tbody.appendChild(tr);
td = document.createElement('td');
td.innerText = i;
tr.appendChild(td);
for (j = 0; j < combined[i].length; j++) {
td = document.createElement('td');
td.innerText = combined[i][j];
tr.appendChild(td);
}
}
}
This will work on tables with any number of rows and any number of cells. I suppose you want to make the sum for every column, that's what this script does.
And as cwolves mentioned, it is more logical to do this serverside. Users that have JS disabled will see the not so clean uncombined table.

Categories