Repeat script for multiple elements - javascript

Hey i have this code:
<body>
<table>
<tr>
<td class="first">100</td>
</tr>
</table>
<h4 class=curs style="display:none">10</h4>
<script>
document.body.onload = function(){
var firstTdVal = document.getElementsByClassName('first')[0].innerHTML;
var secondTdVal = document.getElementsByClassName('curs')[0].innerHTML;
var valueToBeShown = parseInt(firstTdVal)/ parseInt(secondTdVal);
document.getElementsByClassName('first')[0].innerHTML = valueToBeShown ;
}
</script>
</body>
As you see ".first" has a number in it,this number is divied to ".curs" and the result is showed in ".first" too.Now the problem is that for exemple i add 100 more td's with class ".second,.third...,.hundred" in table.How to make script to do the same for all td's as it does for the ".first"(devide to ".curs").How do i do this in my JS by keeping it complex.

Use document.querySelectorAll to get an array of matched elements (matched with CSS selector), then loop through them using forEach, applying you logic one td at a time. Like this:
// querySelector gets the first element matched. textContent get the text of that element
var cursValue = parseInt(document.querySelector(".curs").textContent);
// querySelectorAll get an array of all the matched elements
var tds = document.querySelectorAll("td");
// loop through that array one td at a time
tds.forEach(function(td){
// get the text of the current td
var value = parseInt(td.textContent);
// if the value is not valid (a string for example) return and don't process anymore for this td (go straight to the next one).
if(isNaN(value)) return;
// calculate the new value
value = value / cursValue;
// change the text of this td (update it to the new value)
td.textContent = value;
});
NOTE: querySelector and querySelectorAll match elements using CSS selectors, so to match an element using a class the selector should be ".className", to match it using an ID: "#someID", ... All CSS selectors are accepted (even this one: "#anID>li.some-class a:not([href])").
NOTE2: tds is an array, so if you don't want to use forEach you can use a normal for loop (for(var i = 0; i < tds.length; i++) ...).

This will iterate over your table (be sure to set the table ID) (open dev console to view output but it's pretty straight forward.)
var table = document.getElementById("myTable");
for (var row of table.rows) {
for (var col of row.cells) {
console.log(col.className, col.innerHTML); //Class names and the values of the elements.
}
}
If you need anymore help please ask because I do not fully understand what you're trying to do here.

Here's a way where you put the number to be divided by in the first td, the number to divide by in the second td, and the result will be placed in the third td.
var trs = document.getElementsByTagName('tr');
for (var i = 0; i< trs.length; i++) {
var tds = trs[i].getElementsByTagName('td'),
first = tds[0].textContent,
second = tds[1].textContent,
third = tds[2],
result = (parseInt(first) / parseInt(second));
third.innerHTML = result;
}
<table>
<tr>
<td>10</td>
<td>2</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>2</td>
<td></td>
</tr>
</table>

Related

Question on Traversing an HTML table with JavaScript and DOM Interfaces

I followed the example here: https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Traversing_an_HTML_table_with_JavaScript_and_DOM_Interfaces
But I have 2 things I can't figure out.
The first is how do I add a class name for all the td elements?
The second, is how do I inject this table into a div named "main",
rather than document.getElementsByTagName("body")[0];
I don't really understand the [0] at the end of the document.getElementsByTagName("body"), why is it necessary?
The first is how do I add a class name for all the td elements?The
first is how do I add a class name for all the td elements?
classList.add
The second, is how do I inject this table into a div named "main"
getElementById
I don't really understand the [0] at the end of the
document.getElementsByTagName("body")
Because getElementsByTagName is generic. It can return multiples for any tag. [0] says "give me the first", and since it's BODY, we pretty much are sure there's only one.
function start() {
// get the reference for the body
var mybody = document.getElementById("main");
// creates <table> and <tbody> elements
mytable = document.createElement("table");
mytablebody = document.createElement("tbody");
// creating all cells
for(var j = 0; j < 3; j++) {
// creates a <tr> element
mycurrent_row = document.createElement("tr");
for(var i = 0; i < 4; i++) {
// creates a <td> element
mycurrent_cell = document.createElement("td");
mycurrent_cell.classList.add("myClass");
// creates a Text Node
currenttext = document.createTextNode("cell is row " + j + ", column " + i);
// appends the Text Node we created into the cell <td>
mycurrent_cell.appendChild(currenttext);
// appends the cell <td> into the row <tr>
mycurrent_row.appendChild(mycurrent_cell);
}
// appends the row <tr> into <tbody>
mytablebody.appendChild(mycurrent_row);
}
// appends <tbody> into <table>
mytable.appendChild(mytablebody);
// appends <table> into <body>
mybody.appendChild(mytable);
// sets the border attribute of mytable to 2;
mytable.setAttribute("border","2");
}
start();
.myClass {
color:red;
}
<div id="main"></div>

JS create new child TR with two TD bits of information

I have the following problem - I am having difficulty creating the new TR row dynamically and then getting it to insert the data as a new table (TD) line.
The full question is as below;
Create a script that inserts a new row with the values March and £580 as the last child of the following HTML table.
<table id=”takings”>
<tr>
<td>January</td>
<td>£100</td>
</tr>
<tr>
<td>February</td>
<td>£300</td>
</tr>
// insert here
</table>
My attempt or idea was to create the TR first and then for each item in the text array add a TD within that newly created TR. However this doesn't seem to create anything.
My JS is as below;
function insertNode(newNodeTypeTD, newNodeTypeTR, newNodeTextArray, element) {
let parentElement = document.getElementById(element);
let newTR = document.createElement(newNodeTypeTR);
for (let i = 0; newNodeTextArray.length; i++) {
let newText = document.createTextNode(newNodeTextArray);
newTR.appendChild(newText);
parentElement.insertBefore(newTR, parentElement.children[i]);
}
}
window.onload = function() {
insertNode("td", "tr", ["March", "£580"], "takings")
}
Note this line: for (let i = 0; newNodeTextArray.length; i++) {
newNodeTextArray.length is 1 or greater, so this condition always returns true.
What you likely meant to do was
for (let i = 0; i < newNodeTextArray.length; i++) {

Remove all table rows except one with a given class

I have a table rendered dynamically. There's one <tr class="dolly"> somewhere inside its <tbody> that serves as a reference row - it gets cloned and filled with data later. I need to delete all rows except that one.
What I tried:
for loop: uses an increment which quickly gets invalid as the rows are deleted
while loop: continues until all rows are deleted, which never happens because of the condition
Please let me know if you have any ideas. Please no jQuery.
use document.querySelectorAll('tr:not(.dolly)') to select all tr's except with class .dolly and then iterate over it to remove the filtered tr's.
document.querySelectorAll('table tr:not(.dolly)').forEach((tr) => {
tr.remove();
});
<table>
<tr class="dolly">
<td>One</td>
</tr>
<tr>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
</tr>
</table>
I am gonna share my solution here.
function deleteAllOtherRowExceptOne(exceptionIndex) {
const tableBody = document.querySelector('#my-table-tbody')
const tableBodyRowLength = tableBody.rows.length
let deleteIndex = 0
for (let i = 0; i < tableBodyRowLength; i++) {
if(i == exceptionIndex){
deleteIndex++
} else {
tableBody.deleteRow(deleteIndex)
}
}
}
Here is my solution for this question.
// Fetch all rows
const rows = document.querySelectorAll('tr');
// Iterate through the rows and remove those that do not have the desired
class
const className = 'class-name';
rows.forEach(row => {
if (!row.classList.contains(className)) {
row.remove();
}
});
I took refernce from here - https://bbbootstrap.com/code/delete-all-table-rows-except-one-given-class-javascript-61232938

Javascript-Collapsing and expanding table rows based on hierarchy

I have the following table generated by a cgi script:
<table>
<tr id='vfipbb'><td>col 1,0</td><td>col 1,1</td></tr>
<tr id='vfipbb.alipbb'><td>col 2,0</td><td>col 2,1</td></tr>
<tr id='vfipbb.esipbb'><td>col 3,0</td><td>col 3,1</td></tr>
<tr id='vfipbb.esipbb.esipbb_madrid'><td>col 4,0</td><td>col 4,1</td></tr>
<tr id='vfipbb.esipbb.esipbb_barcelona'><td>col 5,0</td><td>col 5,1</td></tr>
</table>
This is just a sample of what it would look like, but the important bit to note is the id.
when the webpage first loads all rows are collapsed except for the root context (vfipbb). I want to enable functionality when the root context is clicked it will expand all child rows listed under this, for example (alipbb), (esipbb) and if one of the child rows is clicked it will expand all grandchildren rows, for example (esipbb_madrid) (esipbb_barcelona).
Is there any efficient way of doing this in javascript based on ID? Any pointer in the right direction would be greatly welcome!
Not a working code, but something to get you started
// add click handlers to all tr
var tr0 = document.getElementsByTagName("tr");
for (var i = 0; i < tr0.length; i++) {
tr0[i].addEventListener("click", openChild);
}
function openChild() {
var id = this.id;
//regex that matches a string beginning with
//the id followed by dot and some other words
var regex = new RegExp("^" + id + ".[a-z_]+$", "g");
var tr1 = document.getElementsByTagName("tr");
//browse through the tr(s)
for (var i = 0; i < tr1.length; i++) {
//Learn regex test function!
if (regex.test(tr1[i].id)) //if a match found
//display children
document.getElementById(tr1[i].id).style.visibility = "visible";
}
}

Jquery Iterate over table and highlight cells that have changed

I have a table that is a history of a mysql record.
I want to add a button that will highlight the changes.
<table>
<tr>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
<tr>
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
In this example the 600 would be highlighted as it was 300 and is now 600.
UPDATE: Thanks, I should have said there would be more than 2 rows. could be upto 20 rows
This jsFiddle shows an example that will iterate over a table of any size and highlight the cells that have changed from the previous row.
$(function() {
var $rows = $("tr");
for (oldIndex = 0; oldIndex < $rows.length-1; oldIndex++) {
var newIndex = oldIndex + 1;
var $oldCols = $("td", $rows[oldIndex]);
var $newCols = $("td", $rows[newIndex]);
for (col = 0; col < $oldCols.length; col++) {
var $newCol = $($newCols[col]);
if ($($oldCols[col]).html() != $newCol.html()) {
$newCol.addClass("highlight");
}
}
}
});​
Your solution should go along these lines. Assuming set1 and set2 are id's of two trs here is a sample code (not tested).
var s1 = $('tr#set1 td');
var s2 = $('tr#set2 td');
var l = $('tr#set1 td').length;
for(var i =0; i<l i++){
if(s1.eq(i).text() != s2.eq(i)){
$(s2.eq(i)).highlight();
}
}
$('table tr.new td').each(function(i){
//First TR td, Previous Rows
td = $(this);
check = $('table tr.prev td:eq('+i+')');
if(td[0].innerText != check[0].innerText)
{
check.addClass('Changed');
}
})​
This should do it but you need to add 2 classes:
<table>
<tr class="new">
<td>150</td>
<td>200</td>
<td>300</td>
</tr>
<tr class="prev">
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>​
Demo: http://jsfiddle.net/hjXZd/1/
Hope this helps.
I advise you to do an attr for each TD and place the mysql id in there so that you will only compare the rows that are the same in the DB, otherwise if your first list has more items then the second list the results will be corrupt.
Assuming your table has the id results, here is a solution:
var topRow = $('table#results tr:eq(0)');
var bottomRow = $('table#results tr:eq(1)');
topRow.find('td').each(function(index,item){
var shadow = bottomRow.find('td:eq('+index+')');
if($(item).contents().text()!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
Update: this solution compares the top row with all following ones:
$('table#results tr:eq(0) td').each(function(index,item){
var orig = $(item).contents().text();
$('table#results tr:gt(0)').find('td:eq('+index+')').each(function(index2,item2){
var shadow = $(item2);
if(orig!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
});
Using Jquery .live you can handle multiple elements.
See here
http://api.jquery.com/live/
You have to give ids for the changed values.. which can be inside divs.
Hope td also may work
On button click using this .live you can chnage style of div
like highlighting.
Use addClass function os jquery itslef or you can add css using jquery add

Categories

Resources