javascript to loop through table rows with a classname - javascript

Here is the following table code and I want to store all TD values into an Array.
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
For this I have written this following code:
function checkForm() {
var table = document.getElementsByClassName("item-row");
var arr = new Array();
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
arr.push(row.cells[j].val);
}
}
}
But this gives me no output...I am new to javascript so may be am missing something in big time.

Your code is almost right, the thing is that rows property work for tables not for trs so you have to take a table instead of the tr directly.
The other thing is that getElementsByClassName returns an array of your elements so you have to use [index] to get your element.
The last thing is that to get the value for the cell you can't use val, so use firstChild to get the child and value to get the value as in the code, or better as #pawel suggest directly cell.textarea :)
Try with this code:
function checkForm() {
var table = document.getElementsByClassName("yourTable")[0];
var arr = new Array();
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
arr.push(row.cells[j].firstChild.value);
}
}
console.log(arr);
}
<table class="yourTable">
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
</table>
<input type="button" onclick="checkForm();" value="check form"/>
Hope this helps,

What you have is a good first effort for being new to JavaScript, but, yes, there are quite a few items that need updating. :)
Here is what you would need to do what you are trying to do:
function checkForm() {
var rows = document.getElementsByClassName("item-row");
var arr = new Array();
for (i = 0; i < rows.length; i++) {
var cols = rows[i].getElementsByTagName("td");
for (j = 0; j < cols.length; j++) {
arr.push(cols[j].textContent);
}
}
}
You need to cycle through each row . . . the easiest way to do this by going from i = 0 to i < rows.length in your for loop.
Once you have a row, you need to gather all of the columns in the row, by finding all of the <td> elements (var cols = rows[i].getElementsByTagName("td"););
Then, you loop through each of those, just like you did with the rows (j = 0 to j < cols.length
Finally, to get the text contained in each td, you use the textContent property . . . values (i.e., the value property) are used only for <input> elements
There were a couple of syntax errors in there, too (you used , instead of ;, when building your for loop and you used val instead of value, when attempting to get the td content), but that was all that I saw.
Edit: I'm also assuming that you just did not paste your <table> tags in when you added your HTML, but, if you didn't your <tr> tags must be inside a <table.
Edit 2: My solution also skips the looking at the tags inside the <td> elements, since they are not standard (4 contain <textarea> inputs and the 5th a <span>). If you want to go down one more level of detail, you could use .value on the textareas and (again) .textContent on the <span>. By using .textContent one level up, you are ignoring all HTML tags insid the <td> tags and returning only the text.

Related

Getting a checkbox from a table field

Good afternoon, below is the code in it I am getting fields from my table. The 0 field contains a checkbox, how can I find out if it is checked or not(true or false)? You need to change this line: console.log (td.item (f));
var table = document.getElementsByClassName("table-sm");
for (var i = 0; i < table.length; i++) {
var tr = table.item(i).getElementsByTagName("tr");
for (var j = 0; j < tr.length; j++) {
var trr = tr.item(j);
var td = tr.item(j).getElementsByTagName("td");
for (var f = 0; f < td.length; f++) {
if (f === 0) console.log(td.item(f));
console.log(td.item(f).innerText);
}
}
}
Firstly, please learn about JavaScript Table API is much better than just making complex for-loops.
Next time please add full code (HTML/JavaScript) so people can help you.
Now let's fix your code.
Suppose we have this table
<table class="table-sm" id="myTable">
<thead>
<tr>
<th>Checkbox</th>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="selected[]" checked /></td>
<td>1</td>
<td>Mohammed</td>
</tr>
<tr>
<td><input type="checkbox" name="selected[]" /></td>
<td>2</td>
<td>Ali</td>
</tr>
</tbody>
</table>
and we want to get the first item of each rows, and check whether the checkbox is checked or not.
We can do it easly using JS Table APIs.
Get the table by it's ID.
var table = document.getElementById("myTable");
Get the table rows
I use Array.from() to convert HTMLCollection to normal array, so I can use Array APIs (Like .forEach).
var rows = Array.from(table.rows);
Loop into table rows, and get cells of each row.
rows.map((row) => {
var cells = Array.from(row.cells);
// TODO add logic here.
});
Get the firstChild of first cell.
rows.map((row) => {
var cells = Array.from(row.cells);
if (Array.isArray(cells) && cells.length > 0) {
var firstChild = cells[0].firstChild;
console.log(firstChild.checked);
}
});
Live Example

How to find the last table cell which doesn't have text value and put a message?

I want to detect the last table row cell of a table which doesn't have any value (text).
var all_product_cell = document.getElementsByClassName("product-cell");
for (var i = 0; i < all_product_cell.length; i++) {
var td = all_product_cell[i];
alert(all_product_cell.length);
}
This code returns the table rows length... but I don't know how to check the last row which is clean and put there a message "hello!"...
UPDATE :
With this code system find last cell and put HELLO, but how I check the last cells who haven't text value and put the Hello there?
var all_local_cell = document.getElementsByClassName("product-cell");
for (var i = 0; i < all_local_cell.length; i++) {
var td = all_local_cell[i];
total_rows = all_local_cell.length-1;
all_product_cell[total_rows].value = "HELLO";
const productTable = document.querySelector(".your-product-table"); // get the table
const textOnLastCell = productTable
.rows[productTable.rows.lenght -1] // get last row
.cells[productTable.rows[productTable.rows.lenght -1].cells.lenght -1] // get last cell of last row
.innerText // get inner text
You can get last row of table by using below line :
var product_table = document.getElementsByClassName("product-cell");
console.log(product_table);
for (var i = 0; i < product_table.length; i++) {
total_rows = product_table[i].rows.length;
last_row = product_table[i].rows[total_rows-1];
last_row_length = last_row.cells.length;
last_column = last_row.cells[last_row_length-1]; // directly get last cell
If(last_column.innerHTML() == “”){
last_column.innerHTML = “Hello friend”;
}
console.log(last_column.innerHTML);
for(var j =0;j<last_row.cells.length;j++){ // you can find through loop using which cells is empty
console.log(last_row.cells[j]);
}
// console.log(last_row);
}
If you give html code will help better way.
https://codepen.io/aviboy2006/pen/ZEYBWWE
Here's a table with two empty TD'S.
The function will get an array of all TD's with the class product-cell and loop through each cell and check if innerHTML is empty, and then it will set lastTD to the last empty TD and set its innerHTML to "Hallo"
setTextLastEmptyCell()
function setTextLastEmptyCell(){
let tds = document.getElementsByClassName('product-cell')
for(let td of tds){
if(td.innerHTML === '') lastTD = td
}
lastTD.innerHTML = 'HALLO'
}
<table>
<tr>
<td class="product-cell">ABC</td>
<td class="product-cell">DEF</td>
<td class="product-cell">CBA</td>
</tr>
<tr>
<td class="product-cell"></td>
<td class="product-cell">CDA</td>
<td class="product-cell">ACB</td>
</tr>
<tr>
<td class="product-cell">ABC</td>
<td class="product-cell"></td>
<td class="product-cell">DEF</td>
</tr>
</table>

How to add and subtract numbers via JavaScript in an HTML table

I want to add numbers in <td></td> below via JavaScript. For example using the following description:
<td id='last'> + formatNumber(data.tickers[key].last) + </td>
<td id='high'> + formatNumber(data.tickers[key].high) + </td>
<td id='low'> + formatNumber(data.tickers[key].low) + </td>
How do I change the text of table data elements via JavaScript?
<td id='new1'> = + <td id='last'> + <td id='high'> + </td>
<td id='new2'> = + <td id='high'> + <td id='loww'> + </td>
Try this:
// these target the cell elements
let last = document.getElementById("last");
let high = document.getElementById("high");
let low = document.getElementById("low");
let new1 = document.getElementById("new1");
let new2 = document.getElementById("new2");
// now we convert cell content to numbers, add them and make them 2 decimal places.
new1.textContent = (parseFloat(last.textContent) + parseFloat(high.textContent)).toFixed(2);
new2.textContent = (parseFloat(high.textContent) + parseFloat(low.textContent)).toFixed(2);
td {
border: solid 1px;
}
<table>
<tr>
<th>last</th>
<th>high</th>
<th>low</th>
<th>new1</th>
<th>new2</th>
</tr>
<tr>
<td id='last'> 23.40 </td>
<td id='high'> 28.20 </td>
<td id='low'> 22.10 </td>
<td id='new1'></td>
<td id='new2'></td>
</tr>
</table>
First I'm going to make your life a bit easier. Instead of using document.getElementsByTagName('tr')[3].getElementsByTagName('td')[2] to get the fourth tr element's third td element ([0] = first, [2] = third, etc) this will help make your code much much easier to read. You don't need id attributes on every element if you know how reliable code and order are by default.
function tag_(t)
{//Example: tag_('body')[0];
return (document.getElementsByTagName(t)) ? document.getElementsByTagName(t) : false;
}
Object.prototype.tag_ = function(t)
{//Example: id_('unique_id').tag_('td')[0];
return (this.getElementsByTagName && this.getElementsByTagName(t) && this.getElementsByTagName(t).length > 0) ? this.getElementsByTagName(t) : false;
}
Secondly the easiest way to both read and write data to any element is to use textContent.
Read the fourth td on the third tr:
//Read an element's text node:
console.log(tag_('tr')[2].tag_('td')[5].textContent);
//Write to an element's text node:
tag_('table')[0].tag_('tr')[2].tag_('td')[5].textContent = '1,234');
JavaScript is a bit strict when it comes to types. So if you need to do some math with text content that you just read you need to convert it:
Number(tag_('tr')[1].tag_('td')[5].textContent);//'123' becomes `123`
Number(tag_('tr')[2].tag_('td')[2].textContent);//'a123' becomes `NaN` (Not a Number)
If I recall correctly I recently used the following to strip non-numeric text from a string:
var my_number = Number('String or replace with object reference'.replace(/\D/g,''));
Now that you're getting the read/write aspects and overcoming some of the more oddities associated with it I'll iterate over...iteration! You may already know this though I'm presuming a full answer is more desirable than a partial answer for not just you though also others reading this in the future.
var table = tag_('table');
for (var i = 0; i < table.length; i++)
{
console.log(table[i]);
var tr = table[i].tag_('tr');//Whatever table[i] is and it's table rows.
for (var j = 0; j < tr[i].length; j++)
{
console.log(tr[j]);
var td = table[i].tag_('tr')[j].tag_('td');//All the table data elements.
for (var k = 0; k < td.length; k++)
{
//apply read/write conditions here.
//potentially call a second global function to keep your code reusable.
}
}
}
That should help you get far enough with specific and iteral targeting of table data elements to help you learn and achieve your goals.

Dynamically delete multiple columns in html table

I am trying to delete multiple columns from html table using javascript.
The logic it is using is that it searches in top row for tag "" and then deletes that column.
The problem is if only one cell in top row is having '', then it deletes that columns fine, but if there are multiple columns it throws error.
Here is my code
<!DOCTYPE html>
<html>
<body>
<table style="width:100%" border='1' id='Just_for_california'>
<tr>
<td><span></span></td>
<td>S</td>
<td><span></span></td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</body>
<script>
var dataTable_length = document.getElementById('Just_for_california').rows[0].cells.length;
var count_rows = document.getElementById('Just_for_california').rows.length;
var column_array = [];
for(var i=0; i<dataTable_length; i++)
{
var str = document.getElementById("Just_for_california").rows[0].cells[i].innerHTML;
if(str.search("<span></span>") != -1)
{
column_array.push(i);
}
}
var len = column_array.length;
for(var i=count_rows-1 ; i>=0;i--)
{
rows_number = document.getElementById('Just_for_california').rows[i];
console.log("row_number:"+i);
for(var j=0; j<len;j++)
{
rows_number.deleteCell(column_array[j]);
}
}
</script>
</html>
It happens because you calculate indexes incorrectly when you delete cells. I refactored you code (making it clearer) and it seems to work now:
var table = document.getElementById('Just_for_california'),
rows = table.rows;
for (var i = 0; i < rows[0].cells.length; i++) {
var str = rows[0].cells[i].innerHTML;
if (str.search("<span></span>") != -1) {
for (var j = 0; j < rows.length; j++) {
rows[j].deleteCell(i);
}
}
}
The problem is that you are trying to remove cells "horizontally" in the row. So say you want to delete cells at indexes 1 and 3 and there are 4 columns in the table. When you delete the first cell 1 it works fine. However then you move to the right and try to remove cell at index 3. This fails because since you have already removed cell 1, there is no cell with index 3 anymore. The maximum index now is 2. Hence the error.
In my improved code I'm removing columns "vertically", so such an issue can't happen.
Demo: http://jsfiddle.net/t2q60aag/

JavaScript -- reading a table

This is a function that, when passed a table as an argument, applies a different style color to alternating rows to improve readability. i.e. first row is dark grey, second row is light grow, third row is dark grey etc.
As mentioned, it gets passed the whole table as an argument. None of the rows have ids. Starting at this line var aTBODY = oTable.getElementsByTagName("tbody");, I understand what is happening. Namely, it gets the table body and then all the rows within it and stripes them alternately.
1) But what is happening exactly in the first five lines of the program? The comments don't explain it clearly for me.
2) does looping over a table length (i.e idArray.length) create an array of rows? what is happening with var id = idArray[indx]; ?
3) When it says, in the comments, get the table that corresponds to this id, using the code var oTable = document.getElementById(id) why is this a necessary step? what is happening?
thank you if you can explain
function createStripedTable(idArray) {
// for each table ID that we're given, stripe all the rows.
for (var indx = 0; indx < idArray.length; indx++) {
var id = idArray[indx];
// get the table that corresponds to this ID
var oTable = document.getElementById(id);
if (oTable == null)
return;
// get its table body, which contains all the TR tags
var aTBODY = oTable.getElementsByTagName("tbody");
// set the CSS class for each one of the TR tags
for (var i = 0; i < aTBODY.length; i++) {
// get an array of all the TR tags in the TBODY
var aTR = aTBODY[i].getElementsByTagName("tr");
for (var j = 0; j < aTR.length; j++) {
// the % operator divides the given number by another
// and returns the remainder. This is how we alternate the
// rows.
aTR[j].className = (j % 2 == 1) ? "stripe1" : "stripe2";
}
}
}
}
Here's the code that's calling it.
function() {createStripedTable(new Array("MSFTQuotes"))
Here's an excerpt of the one and only one table that is passed.
<body>
<table id="MSFTQuotes">
<thead>
<tr>
<th colspan="7" align="center">
<span class="TableTitle">Stock Activity for Aug 5, 2008 - Nov 5, 2008 </span>
</th>
</tr>
<tr>
<th align="center" width="14%">
<div align="right" class="style5">
Date</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Open</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
High</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Low</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Close</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Volume</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Adj Close</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td align="right">
5-Nov-08
</td>
<td align="right">
29.21
</td>
<td align="right">
29.36
</td>
<td align="right">
29.03
</td>
<td align="right">
29.31
</td>
<td align="right">
95,337,696
</td>
<td align="right">
29.31
</td>
The function accepts an array of id values corresponding to table elements. It loops through those IDs and does its striping work on all of the tbody elements within the tables.
Somewhat more annotated (see TJC:s):
function createStripedTable(idArray) {
// for each table ID that we're given, stripe all the rows.
// TJC: Loop through all of the IDs in the given array
for (var indx = 0; indx < idArray.length; indx++) {
// TJC: Get the ID value for index `indx` in the array
var id = idArray[indx];
// get the table that corresponds to this ID
var oTable = document.getElementById(id);
if (oTable == null) // TJC: Invalid ID, ignore it
return;
// get its table body, which contains all the TR tags
// TJC: Get the `tbody`s under the table. One table
// can have multiple `tbody` elements.
var aTBODY = oTable.getElementsByTagName("tbody");
// set the CSS class for each one of the TR tags
for (var i = 0; i < aTBODY.length; i++) {
// get an array of all the TR tags in the TBODY
// TJC: It's actually a NodeList, but you can largely
// treat it as an array
var aTR = aTBODY[i].getElementsByTagName("tr");
for (var j = 0; j < aTR.length; j++) {
// the % operator divides the given number by another
// and returns the remainder. This is how we alternate the
// rows.
aTR[j].className = (j % 2 == 1) ? "stripe1" : "stripe2";
}
}
}
}
The good news is that IE9 finally supports the nth-child pseudo-class, so someday you'll be able to stop doing this with code.
idArray is an array of all IDS for more than one table. This function will change the alternate rows for each of the tables whose id is in idArray.
The outer loop is iterating through ids. The first five lines inside the loop are assuming they are ids of tables, and fetching the contents of the table element corresponding to each ID.
The next five lines in the loop then fetch the table body contents and change the css class of alternate rows.
Add these lines before the first for loop in the code
var tabarray=new Array();
tabarray.push(thetableidYoupassed);
idArray=tabArray
'thetableidYoupassed' is the actual argument with which you called the function 'createStripedTable'
Keep the rest of the code as it is...This should work fine...
Your method accepts an array of table IDs. So all the tables need to have IDs.
function createStripedTable(idArray) { //idArray is an array of table IDs
Then it loops through them and gets the ID one by one
for (var indx = 0; indx < idArray.length; indx++) {
var id = idArray[indx]; //this is the ID of a table
Then it checks whether the table actually exists in the DOM or not
var oTable = document.getElementById(id); //IF the table with a matching ID is not found, you get NULL
if (oTable == null)
return; //no table that matches the ID? return
Ideally, that line should be continue or something similar. Because in this instance. If you pass your method an array like ['table1', 'table2', 'faketable', 'table3'], your method won't strip table3 because it never gets there in the array (because of the return)

Categories

Resources