I am using the following code to traverse one forum
var formWithTable = document.getElementsByTagName("table")[0];
var table = formWithTable.getElementsByTagName("tbody")[0];
var rows = table.getElementsByTagName("tr");
for(i = 0; i < rows.length; i++)
{
var cols = rows[i].getElementsByTagName("td");
for (j = 0; j < cols.length; j++)
{
...
}
}
The HTML document is as follows:
<div>
<table class="inventory sortable" id="listContainer_datatable" summary="Properties of various threads" title="Properties of various threads">
<thead>
<tr>
...
<tbody id="listContainer_databody">
<tr id="listContainer_row:0" class="">
<td class="smallCell" valign="top">
<input type="checkbox" name="formCBs" value="2161433" id="listContainer_formCBs2161433" title="Add a new message." />
<label for="listContainer_formCBs2161433" id="listContainer_formCBs2161433Label" class="hideoff">
</label>
</td>
...
</table>
</div>
However, I do not know that why document.getElementsByTagName("table")[0] returns "undefined".
Any help is very appreciated.
What you really should be using is jQuery. Then you can just do this:
$("table")[0]
to select the first table of the document. Simple as that.
In other news, if that is your document, it isn't valid HTML, so Javascript DOM isn't guaranteed to work.
Your script is fine, the only problem might be the script is added before the table is added to the dom, that could be the cause of the problem.
The solution is to move the script to window.onload
window.onload = function(){
var formWithTable = document.getElementsByTagName("table")[0];
var table = formWithTable.getElementsByTagName("tbody")[0];
var rows = table.getElementsByTagName("tr");
for(i = 0; i < rows.length; i++) {
var cols = rows[i].getElementsByTagName("td");
for (j = 0; j < cols.length; j++) {
console.log(cols[j].innerHTML)
}
}
}
Demo: Fiddle
Related
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>
I'm using javascript to modify a page's styling and it's working great. The next step however is to change the styling of the first column of a table. How can I identify and set the styling of the first column only? My other changes so far are based on ID or based on a number of items having a class. In this example I just know they are TH or TD elements, and I want to change the ones in the first column.
In case anyone asks, this is my code so far... this is working and doesn't include anything to do with setting the style of the first column
function rotate_headers() {
const collection = document.getElementsByTagName("th");
for (let i = 0; i < collection.length; i++)
{
collection[i].innerHTML =
'<div style="padding-left: 100%;"><div style="transform: translate(7px, 3px) rotate(315deg); width: 30px;"><span style="border-bottom: 1px solid #ccc; padding: 5px 10px; color:grey;"' + collection[i].innerHTML + '</span> </div></div>';
// collection[i].style.background = "#6877c3"; //
//collection[i].style.height = "100px"; //
}
const collection2 = document.getElementsByClassName("table-bordered");
for (let i = 0; i < collection2.length; i++)
{ collection2[i].style.border = "0px";
collection2[i].style.marginTop = "95px";
}
const collection3 = document.getElementsByClassName("highlight");
for (let i = 0; i < collection3.length; i++)
{ collection3[i].classList.remove("highlight"); }
const collection4 = document.getElementsByClassName("table-content");
for (let i = 0; i < collection4.length; i++)
{ collection4[i].style.padding = "1rem 1rem"; }
const collection5 = document.getElementsByClassName("table-content");
for (let i = 0; i < collection5.length; i++)
{ collection5[i].style.width = "100px";
collection5[i].style.position = "relative";
collection5[i].style.whiteSpace = "nowrap";
collection5[i].style.overflowX = "scroll";
collection5[i].style.overflowY = "hidden";
}
}
The below code does what I want, but only if my table has an ID... which mine typically do not.
var table = document.getElementById('test');
for (var i = 1; i < table.rows.length; i++) {
var firstCol = table.rows[i].cells[0]; //first column
firstCol.style.background = 'red'; // or anything you want to do with first col
}
The code below does not work... which is my problem
var table = document.getElementsByTagName("table");
for (var i = 1; i < table.rows.length; i++) {
var firstCol = table.rows[i].cells[0]; //first column
firstCol.style.background = 'red'; // or anything you want to do with first col
}
You can just use document.querySelectorAll('tr th:first-child, tr td:first-child') then iterate the result setting the styles you want.
let firstCol = document.querySelectorAll('tr th:first-child, tr td:first-child')
for (let i = 0; i < firstCol.length; i++) {
firstCol[i].style.color = 'red'
}
<table>
<tr>
<th>one</th>
<th>two</th>
<th>three</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
I think you will find answer in next article:
https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics
Styling without
There is one last feature we'll tell you about in this article before we move on. HTML has a method of defining styling information for an entire column of data all in one place — the and elements. These exist because it can be a bit annoying and inefficient having to specify styling on columns — you generally have to specify your styling information on every or in the column, or use a complex selector such as :nth-child.
This question already has answers here:
Why does firstChild not return the first element?
(5 answers)
Closed 5 years ago.
I am trying to deleted selected or all rows using pure javascript. I am unable to delete selected rows. what was the issue in my fiddle
Edit: First row is header so not considering that.
document.getElementById("delete").addEventListener("click", function() {
var tableRef = document.getElementById('links-list');
var tableRows = document.getElementById("links-list").rows;
var checkedIndexes = [];
for (var i = 1; i < tableRows.length; i++) {
var checkboxSelected = tableRows[i] && tableRows[i].cells[0].firstChild.checked;
if (checkboxSelected) {
checkedIndexes.push(i);
}
}
for (var k = 0; k < checkedIndexes.length; k++) {
tableRef.deleteRow(checkedIndexes[k]);
}
});
This sould be something like the one below, with tableRows[i].querySelector('input').checked, as .firstChild is a textnode. Also, index of tableRows starts with 0.
document.getElementById('delete').addEventListener('click', function() {
var tableRef = document.getElementById('links-list');
var tableRows = document.getElementById('links-list').rows;
var checkedRows = [];
for (var i = 0; i < tableRows.length; i++) {
if (tableRows[i].querySelector('input').checked) {
checkedRows.push(tableRows[i]);
}
}
for (var k = 0; k < checkedRows.length; k++) {
checkedRows[k].parentNode.removeChild(checkedRows[k]);
}
});
As the last loop alters the dom, deleting based on indexes is not reliable when multiple rows are deleted in the same time. So instead of the pure indexes, it should iterate through the actual nodes.
You can use the document.querySelectorAll method with the proper css selector to get all the checkboxes that are checked. Then from the table you can remove those rows with checked checkboxes.
let tableRef = document.getElementById('links-list');
let tbody = tableRef.querySelector("tbody");
let checkedInputs = document.querySelectorAll("input[type='checkbox']:checked");
Array.prototype.slice.call(checkedInputs)
.forEach( input => tbody.removeChild(input.parentNode.parentNode))
Can also be writen with es7 syntax like this
[...checkedInputs].forEach( input => tbody.removeChild(input.parentNode.parentNode))
Use the children property instead of the firstChild one. Also you can enhance your code by avoiding element recalculation. For example, you already found the table, so get the row from it.
Also when you're removing rows, start from the end and go up.
document.getElementById("delete").addEventListener("click", function() {
var tableRef = document.getElementById('links-list');
var tableRows = tableRef.rows;
var checkedIndexes = [];
for (var i = 0; i < tableRows.length; i++) {
var checkboxSelected = tableRows[i].cells[0].children[0].checked;
if (checkboxSelected) {
checkedIndexes.push(i);
}
}
for (var k = checkedIndexes.length - 1; k >= 0; k--) {
tableRef.deleteRow(checkedIndexes[k]);
}
});
<table id="links-list">
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test1
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test2
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test3
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test4
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test5
</td>
</tr>
</table>
<input type=button value="delete" id="delete">
You have 2 errors, first you are not getting the value correctly; secondly, you are deleting in the list that you are iterating, so you need to fix that. Try this:
document.getElementById("delete").addEventListener("click", function() {
var tableRef = document.getElementById('links-list');
var tableRows = document.getElementById("links-list").rows;
var checkedIndexes = [];
for (var i = 1; i < tableRows.length; i++) {
var checkboxSelected = tableRows[i] && tableRows[i].cells[0].firstElementChild.checked;
if (checkboxSelected) {
checkedIndexes.push(i);
}
}
for (var k = 0; k < checkedIndexes.length; k++) {
tableRef.deleteRow(checkedIndexes[k]-k);
}
});
fiddle
I'm attempting to iterate through a html table in javascript and update the id's of the list items within a td tag. I'm currently having trouble on accessing these elements. The tags I need to access are;
<td>
<li id='1'>Curly</li>
<br />
<li id='2'>Larry</li>
<br />
<li id='3'>Moe</li>
</td>
My current JavaScript is below which gets me to the cell. Can anyone advise how to access the Id's of the li?
var table = document.getElementById("tbl_calendar");
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
}
}
You can select all the lis within that cell in the example below using querySelectorAll. Also its not valid HTML to have lis without wrapping them in a ul or ol.
Fiddle: http://jsfiddle.net/AtheistP3ace/ukgfekey/
JS:
var table = document.getElementById("tbl_calendar");
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
var li = col.querySelectorAll('li');
for (var index = 0; index < li.length; index++) {
alert(li[index].id + ': ' + li[index].textContent);
}
}
}
HTML:
<table id="tbl_calendar">
<tr>
<td>
<ul>
<li id='1'>Curly</li>
<br />
<li id='2'>Larry</li>
<br />
<li id='3'>Moe</li>
</ul>
</td>
</tr>
</table>
You also tagged jQuery so in best efforts to be fully explained.
Fiddle: http://jsfiddle.net/AtheistP3ace/ukgfekey/1/
var table = document.getElementById("tbl_calendar");
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
var li = $(col).find('li');
for (var index = 0; index < li.length; index++) {
alert($(li[index]).attr('id') + ': ' + $(li[index]).text());
}
}
}
And as mentioned in comments you don't need all those loops. If you just want all lis from a table you could do this:
Fiddle: http://jsfiddle.net/AtheistP3ace/ukgfekey/2/
var table = document.getElementById("tbl_calendar");
var li, lis = table.querySelectorAll('tr td li');
for (var index = 0; index < lis.length; index++) {
li = lis[index];
alert(li.id + ': ' + li.textContent);
}
you might consider using jQuery something like this
$(document).ready(function(){
$( "td > li" ).each(function() {
$( this ).attr("id","foo" );
});
});
AtheistP3ace already post a good answer but I'm new here and wanted to try to answer myself so here is a fiddle I made, not sure if it's what you want, I used jquery as I see it in your tags : JSFiddle
$("td").each(function() {
$(this).find('li').each(function() {
console.log($(this).attr("id"));
});
});
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;
}
}