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>
Related
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++) {
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>
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>
I am using Javascript to dynamically create a table, and want to make a header-style cell at the beginning of each row. So my question is how I can do this, seeing as insertCell creates only a normal <td> element and not a <th>.
Some things I've tried (via the Tryit editor at w3schools; I have no reason to suspect that any other usage will behave differently) and didn't work:
I've seen a suggestion to create the <th> element independently and then add it to the <tr> element as a child. When I do this, however, it is not added as a table cell, i.e. it is not affected by the table border, does not count toward the array of cells (i.e. if you do insertCell(1), it inserts after the first cell not counting the <th>), and does not get the special bold/center format for a <th> cell.
I've attempted to use insertCell to make a dummy cell and then replaceChild with an independently created cell; this had the same result as above.
I've tried to make a <td> cell via insertCell and simply bold and center it manually, but myCell.style.fontWeight="bold" and myCell.align="center" don't seem to work (they just end the function, as bad commands do in JavaScript), and likewise trying to use CSS doesn't work. So maybe I just have bad syntax or something, but I've got no clue what to do. Any help would be appreciated.
Attempt 1:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to insert new cell(s) at the end of the table row.</p>
<table border="1">
<th>1</th>
<td>2</td>
</tr>
<tr id="myRow">
</tr>
<tr>
</table><br>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction()
{
var newRow = document.getElementById("myRow");
var header=document.createElement("th").appendChild(document.createTextNode("a"));
newRow.appendChild(header);
var enablesLoc=newRow.insertCell(0).appendChild(document.createTextNode("b"));
}
</script>
</body>
</html>
Result: "1" is bolded with a border, "2" and "b" are unbolded with a border (as they should be), "a" is unbolded with no border.
Attempt 2:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to insert new cell(s) at the end of the table row.</p>
<table border="1">
<th>1</th>
<td>2</td>
</tr>
<tr id="myRow">
</tr>
<tr>
</table><br>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction()
{
var newRow = document.getElementById("myRow");
var header=newRow.insertCell(0).appendChild(document.createTextNode("a"));
header.style.fontWeight="bold";
var enablesLoc=newRow.insertCell(1).appendChild(document.createTextNode("b"));
}
</script>
</body>
</html>
Result: The button adds cell "a" unbolded but not cell "b".
The following code shows everything that should get you going:
function addTable(){
var table = document.createElement("table");
var tr = document.createElement("tr");
var th = document.createElement("th");
var td = document.createElement("td");
td.innerText = "im a td";
th.innerText = "im a th";
tr.appendChild(th);
tr.appendChild(td);
table.appendChild(tr);
var out = document.getElementById("out");
out.appendChild(table);
}
You have to call the function and an div with id out <div id=out>...</div> must be in the document. Disclaimer: i only tested this code in chrome
Update to address your points
You wrote I've seen a suggestion to create the <th> element independently and then add it to the <tr> element as a child. When I do this
it is not added as a table cell what do you mean by that and what command are you using,
is not affected by the table border the reason could be because it contains not text,
does not count toward the array of cells (i.e. if you do insertCell(1) i do not understand this either. According to the specs on insertCell it insert an empty td and returns a reference. So insertCell has no array, If you try var table = document.getElementById("myTable") and then table.rows[0].cells.length it returns the number of cells including the th-cell.
it inserts after the first cell not counting the th according on my tests at least in chrome this is not the case; it depends on how you call the method: table.rows[1].insertCell(-1); adds a cell at the second row (zero based array) at the end and table.rows[2].insertCell(1); adds in the third row a cell on position 2 (again zero based) if you use table.rows[3].insertCell(0); the cell is inserted into the 4th. row at the beginning,
and does not get the special bold/center format for a th cell this was not the case for me as well
Disclaimer: i only tested this code in chrome
The html
<button onclick="addRow()">add rows</button><br />
<button onclick="addColumn()">add column</button>
<table border="1" id="myTable">
<tr>
<th>1</th>
<td>2</td>
</tr>
</table>
And the javascript
function addRow()
{
var table = document.getElementById("myTable");
var tr = document.createElement("tr");
var th = document.createElement("th");
var td = document.createElement("td");
td.innerText = "im a td";
th.innerText = "im a th";
tr.appendChild(th);
tr.appendChild(td);
table.appendChild(tr);
}
function addColumn(){
var table = document.getElementById("myTable");
var rows = table.rows;
console.log("rows", rows);
for (var i = 0; i < rows.length; ++i) {
// td = rows[i].cells;
var td = document.createElement("td");
td.innerText = i;
rows[i].appendChild(td);
}
}
Based on DOM Level 2 HTML you can not use insertCell since it Insert[s] an empty TD cell into this row. But you want to add a th
According to DOM Level 3 Core you can use appendChild since it adds the node newChild to the end of the list of children of this node. If the newChild is already in the tree, it is first removed.
So therefore you have to create the elements in the right order: create the row, add the first cell as th then add other cells as td by using append child.
You may take a look at a demo of the above code
The .appendChild() method returns the element being appended. Which means on this line:
var header=document.createElement("th").appendChild(document.createTextNode("a"));
...your header variable is actually the text node, not the th element - so then newRow.appendChild(header); appends just the text node to the row, not the new th.
Try something like this instead:
var newRow = document.getElementById("myRow");
var header = document.createElement("th");
header.appendChild(document.createTextNode("a"));
newRow.appendChild(header);
Demo: http://jsfiddle.net/PtzRL/
Note that if you actually want to append new rows then your newRow variable should not be getting a reference to an existing row in the table, you should give an id to the table:
<table id="myTable">
...and then create a new row and add that to the table:
var table = document.getElementById("myTable");
var newRow = document.createElement("tr");
table.appendChild(newRow);
Demo: http://jsfiddle.net/PtzRL/1/
(Note also that the starting html you show has an error: you're missing the first <tr> just after the <table> tag, and you have an extra <tr> just before the closing </table> tag.)
Is this what you were trying to do?
function myFunction = function() {
var newRow, newHeader, newCell;
newRow = document.getElementById("myRow");
newHeader = document.createElement("th");
newHeader.innerText = "a";
newRow.appendChild(newHeader);
newCell = document.createElement("td");
newCell.innerText = "b";
newRow.appendChild(newCell);
}
If you want the button to add new rows rather than filling in a blank row you put there already, try something like this:
HTML:
<body>
<table id="myTable" border="1">
<tr>
<th>1</th>
<td>2</td>
</tr>
</table>
<button onclick="myFunction()">Try it</button>
</body>
JavaScript:
function myFunction = function() {
var myTable, newRow, newHeader, newCell;
myTable = document.getElementById("myTable");
newRow = document.createElement("tr");
newHeader = document.createElement("th");
newHeader.innerText = "a";
newRow.appendChild(newHeader);
newCell = document.createElement("td");
newCell.innerText = "b";
newRow.appendChild(newCell);
myTable.appendChild(newRow);
}
The function need to altered like this I believe...
function myFunction()
{
var newRow = document.getElementById("myRow");
var header=document.createElement("th");
header.appendChild(document.createTextNode("a"));
newRow.appendChild(header);
var enablesLoc=newRow.insertCell(0);
enables.appendChild(document.createTextNode("b"));
}
When hitting areasensornewline_button, a new row gets created and appended to the table. I can change the row ID, but all new dropdownboxes within this row now have id="selectedArea0", id="selectedSensor0" and name="AreaBinding0", name="sensorBinding0". These have to be 1, 2 and so fort. Any help would much be appreciated!!!!
<table border="0" id="areasensor_table">
<tr id="areasensor_row0">
<td id="area_column0">
<select name="areaBinding0" id="selectedArea0"> #for(area <- areas) {
<option value="#area.uniqueid">#area.name</option>}
</select>
</td>
<td id="sensor_column0">
<select name="sensorBinding0" id="selectedSensor0"> #for(sensor <- sensors) {
<option value="#sensor.id">#sensor.name</option> }
</select>
</td>
<td>
<a class="glyphicon glyphicon-plus" id="areasensornewline_button"></a>
</td>
</tr>
</table>
<p>
<p>
<script>
var q = 1;
document.getElementById('areasensornewline_button').onclick = cloneRowAreaSensor;
function cloneRowAreaSensor() {
var row = document.getElementById('areasensor_row0'); // find row to copy
var table = document.getElementById('areasensor_table'); // find table to append to
var clone = row.cloneNode(true); // copy children too
var innerClone = row.innerHTML;
clone.id = 'areasensor_row' + q; // change id or other attributes/contents
q++;
table.appendChild(clone); // add new row to end of table
}
</script>
A trick is to use Regular expression but is far to be perfect ...
function cloneRowAreaSensor() {
var row = document.getElementById('areasensor_row0'); // find row to copy
var table = document.getElementById('areasensor_table'); // find table to append to
var clone = row.cloneNode(true); // copy children too
clone.innerHTML = clone.innerHTML.replace(/0"/g, q + '"');
clone.id = 'areasensor_row' + q; // change id or other attributes/contents
q++;
table.appendChild(clone); // add new row to end of table
}
The added row is placed outside the tbody html tag. You really should use jQuery, il will help you a lot.
Your code only works first time. Create a counter use it to name element.
Example:
var count = 1;
for(i = 0; i<= 10; i++){
var row = document.getElementById('areasensor_row'+ count +'');
}
It is a simple example. You need to restructure your code like this example. (This cicle for isnt better example, but it works at 10 elements)