JavaScript: dynamic delete row operation error - javascript

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;
}
}

Related

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>

Adding table rows and column dynamically with jQuery

I'm trying to add rows and columns to a table using user input values to determine the number of rows and columns dynamically using jQuery. Below is my code which actually adds rows and columns but not according to the user's inputs
function makeGrid() {
let numOfRow = 0; let numOfCol = 0;
$('#submit').on('click', function() {
numOfRow = $('#height').val();
numOfCol = $('#width').val();
for (var i = 1; i <= numOfRow; i++) {
let row = $('.grid-canvas').append('<tr>');
for (col = 1; col <= numOfCol; col++) {
$('tr').append('<td></td>');
}
}
});
}
makeGrid();
Assuming a user inputs numOfRow = 2 and numOfCol = 2, I should have a table like this
<tbody class="grid-canvas">
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
Problem is my code seems to be adding extra but I haven't been able to figure it out. This is the result of my code
<tbody class="grid-canvas">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
How do I fix my code?
try changing your code from:
$('#submit').on('click', function() {
numOfRow = $('#height').val();
numOfCol = $('#width').val();
for (var i = 1; i <= numOfRow; i++) {
let row = $('.grid-canvas').append('<tr>');
for (col = 1; col <= numOfCol; col++) {
$('tr').append('<td></td>');
}
}
});
into this
$('#submit').on('click', function() {
numOfRow = $('#height').val();
numOfCol = $('#width').val();
var body = $('.grid-canvas');
for (var i = 1; i <= numOfRow; i++) {
let row = $('<tr></tr>');
for (col = 1; col <= numOfCol; col++) {
row.append('<td></td>');
}
body.append(row);
}
});
what i have done in the above code is created a separate object for the table's body and then once my rows are created with the columns, I append them back to the table object.
Pure javascript code is here
function f(x, y) {
var rows = x,
rowButtonNumber = y;
var table = document.getElementById("myTable");
table.innerHTML = "";
for (var i = 0; i < rows; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < rowButtonNumber; j++) {
var td = document.createElement("td");
var btn = document.createElement("button");
btn.innerHTML = "btn " + (i + 1);
btn.id = "btn-" + i;
btn.onclick = function() {
alert(this.innerHTML);
};
td.appendChild(btn);
tr.appendChild(td);
}
}
}
function go() {
var row = document.getElementById("row").value;
var col = document.getElementById("col").value;
f(row, col);
}
<html>
<head>
<style>
td {
width: 200px;
height: 200px;
}
button {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
Rows
<input id="row" type="number" placeholder="Rows" />
<br> Columns
<input id="col" type="number" placeholder="Columns" />
<button onclick="go()">Go</button>
<table id="myTable" cellspacing="50">
</table>
</body>
It does not seem you are using the row variable. I would suggest appending newly created td to row instead of $('tr').

Javascript for add cells in table

I have a problem. I need insert cell in a row. The content of cell is an element of an array. But is duplicate... Here my code:
function addFila() {
var iframe = document.getElementById('myFrame');
var table = iframe.contentDocument.getElementsByClassName("head_to_head h2h_home")[0];
var row = table.insertRow(1);
var fila = ["fecha", "liga", "equipolocal", "equipovisitante", "goleslocal", "golesvisitante"];
for (let i = 0; i < 6; i++) {
row.insertCell(i);
for (let x = 0; x <= fila.length; x++) {
row.insertCell(i).innerHTML = fila[i];
}
}
}
What is wrong?
row.insertCell() return new cell. If you want to create cell and use it you should save created cell in variable. You get duplicate because you call insertCell twice. I hope code below can help you
var table = document.querySelector(".table");
var row = table.insertRow(-1);
var fila = ["fecha", "liga", "equipolocal", "equipovisitante", "goleslocal", "golesvisitante"];
for (let i = 0; i < fila.length; i++) {
const insertedCell = row.insertCell(i);
insertedCell.textContent = fila[i];
}
table td {
border: 1px solid lime;
}
<table class="table">
<tbody>
<tr>
<td>cell_1_1</td>
<td>cell_1_2</td>
</tr>
<tr>
<td>cell_2_1</td>
<td>cell_2_2</td>
</tr>
</tbody>
</table>

How to create rows cell loop in js

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>

Show, hide and group columns in jQuery

I have a table and I need to group columns. How is it possible with HTML to tell if columns belong together? I've been looking at colgroup, but I don't know if that's what I need.
I need to create a function with jquery which works somehow like Microsoft Excel's group function, so I can hide unused columns and only show the relevant columns, but also the option to show the other columns.
Take a look at the jqGrid demos. It has functionality for grouping columns and, I believe (at least for older versions) also hiding them.
You could try something like this...
HTML
<table>
<tr>
<td>
First Name
</td>
<td>
Middle Initial
</td>
<td>
Last Name
</td>
</tr>
<tr>
<td>
John
</td>
<td>
C
</td>
<td>
Doe
</td>
</tr>
<tr>
<td>
Jim
</td>
<td>
D
</td>
<td>
Doe
</td>
</tr>
<tr>
<td>
Jane
</td>
<td>
E
</td>
<td>
Doe
</td>
</tr>
</table>
<a onclick="javascript:hideColumn('first')">Hide First Name</a>
<a onclick="javascript:hideColumn('middle')">Hide Middle Initial</a>
<a onclick="javascript:hideColumn('last')">Hide Last Name</a>
JavaScript
<script type="text/javascript">
function hideColumn(column) {
var row = [];
var dataCell = [];
switch (column) {
case 'first': {
var a = document.getElementsByTagName('a');
if(a[0].innerHTML == "Hide First Name")
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[0].style.visibility = "hidden";
}
a[0].innerHTML = "Show First Name";
}
else
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[0].style.visibility = "visible";
}
a[0].innerHTML = "Hide First Name";
}
break;
}
case 'middle': {
var a = document.getElementsByTagName('a');
if(a[1].innerHTML == "Hide Middle Initial")
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[1].style.visibility = "hidden";
}
a[1].innerHTML = "Show Middle Initial";
}
else
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[1].style.visibility = "visible";
}
a[1].innerHTML = "Hide Middle Initial";
}
break;
}
case 'last': {
var a = document.getElementsByTagName('a');
if(a[2].innerHTML == "Hide Last Name")
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[2].style.visibility = "hidden";
}
a[2].innerHTML = "Show Last Name";
}
else
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[2].style.visibility = "visible";
}
a[2].innerHTML = "Hide Last Name";
}
break;
}
}
}
</script>
Since you want to group items by the columns they are in, they will always be in the same spot in the row. There is probably a better/less hardcoded way to do this. But hopefully this example will help.

Categories