Replace first child of <div> with replaceChild function - javascript

I'm writing simple table generator using JavaScript. I wrote function createChild() just like this:
function createTable(row_count, column_count) {
var table = document.createElement("table");
for (row = 0; row < row_count; row++) {
let tr = document.createElement("tr");
for (column = 0; column < column_count; column++) {
let td = document.createElement("td");
td.innerHTML = "a<sub>(" + (row+1) + "," + (column+1) + ")</sub>";
tr.appendChild(td);
}
table.appendChild(tr);
}
table.setAttribute("border", "1");
var tableHolder = document.getElementById("table-container");
var oldTable = tableHolder.firstChild;
if (!oldTable) {
tableHolder.appendChild(table);
}
else {
tableHolder.firstChild.replaceWith(table);
//tableHolder.replaceChild(tableHolder.firstChild, table);
}
}
The problem occurs at these lines:
tableHolder.firstChild.replaceWith(table);
//tableHolder.replaceChild(tableHolder.firstChild, table);
If I use first line, It works alright but when I switch it to second line, It doesn't work with error Uncaught DOMException: Failed to execute 'replaceChild' on 'Node': The node to be replaced is not a child of this node.
I can't figure out what's wrong.. please help.

You accidentally switched the order of the arguments passed to Node#replaceChild. The node to be inserted comes before the node to be replaced, somewhat counter-intuitively:
tableHolder.replaceChild(table, tableHolder.firstChild);
Demo Snippet:
function createTable(row_count, column_count) {
var table = document.createElement("table");
for (row = 0; row < row_count; row++) {
let tr = document.createElement("tr");
for (column = 0; column < column_count; column++) {
let td = document.createElement("td");
td.innerHTML = "a<sub>(" + (row+1) + "," + (column+1) + ")</sub>";
tr.appendChild(td);
}
table.appendChild(tr);
}
table.setAttribute("border", "1");
var tableHolder = document.getElementById("table-container");
var oldTable = tableHolder.firstChild;
if (!oldTable) {
tableHolder.appendChild(table);
}
else {
//tableHolder.firstChild.replaceWith(table);
tableHolder.replaceChild(table, tableHolder.firstChild);
}
}
createTable(10, 10)
<div id="table-container"></div>

please check updated fiddler.there is an update in replace Child.
http://jsfiddle.net/HB7LU/28302/
enter code here`
tableHolder.replaceChild(table, tableHolder.firstChild);

Related

Dynamically created html table data not showing in order as expected

function CreateWeakHeader(name) {
var tr = document.createElement('tr');
var td = document.createElement('td');
td.classList.add("cal-usersheader");
td.style.color = "#000";
td.style.backgroundColor = "#7FFF00";
td.style.padding = "0px";
td.appendChild(document.createTextNode(name));
tr.appendChild(td);
var thh = document.createElement('td');
thh.colSpan = "31";
thh.style.color = "#FFFFFF";
thh.style.backgroundColor = "#7FFF00";
tr.appendChild(thh);
return tr;
}
function htmlTable(data, columns) {
var header = document.createElement("div");
header.classList.add("table-responsive");
var header2 = document.createElement("div");
header2.id = "calplaceholder";
header.appendChild(header2);
var header3 = document.createElement("div");
header3.classList.add("cal-sectionDiv");
header2.appendChild(header3);
if ((!columns) || columns.length == 0) {
columns = Object.keys(data[0]);
}
var tbe = document.createElement('table');
tbe.classList.add("table", "table-striped", "table-bordered");
var thead = document.createElement('thead');
thead.classList.add("cal-thead");
tbe.appendChild(thead);
var tre = document.createElement('tr');
for (var i = 0; i < columns.length; i++) {
var the = document.createElement('th');
the.classList.add("cal-toprow");
the.textContent = columns[i];
tre.appendChild(the);
}
thead.appendChild(tre);
var tbody = document.createElement('tbody');
tbody.classList.add("cal-tbody");
tbe.appendChild(tbody);
var week = 0;
//tbody.appendChild(CreateWeakHeader("Week " + week));
var tre = document.createElement('tr');
for (var j = 0; j < data.length; j++) {
if (j % 7 == 0) {
week++;
tbody.appendChild(CreateWeakHeader("Week " + week));
}
var thead = document.createElement('td');
thead.classList.add("ui-droppable");
thead.appendChild(data[j]);
tre.appendChild(thead);
tbody.appendChild(tre);
}
header3.appendChild(tbe);
document.body.appendChild(header);
}
$("#tb").click(function() {
var header = document.createElement("div");
header.innerHTML = "test";
var d = [header, header, header, header, header, header, header, header];
htmlTable(d, days);
});
var days = ['Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag', 'Zondag'];
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="tb">CreateTable</button>
I'm trying to order the data that I get from my server to match the columns of my table.
My table columns are days from Monday to Sunday. When my data has more than 7items it needs to separate with another td. The td shows me week 1 and when my data has more than 7 items it needs to separate again that shows week 2 etc.
Update
Im now using a snipped verdion of my code.
Hope someone can help me out with this.
Thank you
There's a few things going on in the code that are problematic.
An attempt to add the table cells to the row, and the row to the table, was made on each iteration of the for loop. That would have produced a lot of rows with single cells had it worked.
It didn't work because there was only ever a single instance of tre, the row variable. So that meant the line tbody.appendChild(tre); did nothing, since appendChild won't append an element that already has a parent element.
Because your data was an array of references to HTMLElements with parents, appending them using appendChild did nothing for the same reason.
I've amended the code below to take care of all of these situations.
Firstly, the code will append a clone of the data to the cell if it's an HTMLElement. I expect in your real code you won't need this, but for this example, why not? It then appends the cell to the row and continues to the next data element.
Secondly, when the data iterator is at 7, before it appends the "Week N" header, it appends a clone of the row, if it has cells on it.
Finally, after appending the clone of the row, the code will reset the row variable to a new instance of a tr element, with no cells.
I also made some variable name and formatting changes to your code just so I could more easily work with it.
function CreateWeakHeader(name) {
var tr = document.createElement('tr');
var td = document.createElement('td');
td.classList.add("cal-usersheader");
td.style.color = "#000";
td.style.backgroundColor = "#7FFF00";
td.style.padding = "0px";
td.appendChild(document.createTextNode(name));
tr.appendChild(td);
var thh = document.createElement('td');
thh.colSpan = "6"; // "31"; Why 31? A week has 7 days...
thh.style.color = "#FFFFFF";
thh.style.backgroundColor = "#7FFF00";
tr.appendChild(thh);
return tr;
}
function htmlTable(data, columns) {
var header = document.createElement("div");
header.classList.add("table-responsive");
var header2 = document.createElement("div");
header2.id = "calplaceholder";
header.appendChild(header2);
var header3 = document.createElement("div");
header3.classList.add("cal-sectionDiv");
header2.appendChild(header3);
if ((!columns) || columns.length == 0) {
columns = Object.keys(data[0]);
}
var tbe = document.createElement('table');
tbe.classList.add("table", "table-striped", "table-bordered");
var thead = document.createElement('thead');
thead.classList.add("cal-thead");
tbe.appendChild(thead);
var tre = document.createElement('tr');
for (var i = 0; i < columns.length; i++) {
var the = document.createElement('th');
the.classList.add("cal-toprow");
the.textContent = columns[i];
tre.appendChild(the);
}
thead.appendChild(tre);
var tbody = document.createElement('tbody');
tbody.classList.add("cal-tbody");
tbe.appendChild(tbody);
var week = 0;
//tbody.appendChild(CreateWeakHeader("Week " + week));
var tre = document.createElement('tr');
for (var j = 0; j < data.length; j++) {
if (j % 7 == 0) {
week++;
/* Major changes start here */
// if the row has cells
if (tre.querySelectorAll('td').length) {
// clone and append to tbody
tbody.appendChild(tre.cloneNode(true));
// reset table row variable
tre = document.createElement('tr');
}
// then append the Week header
tbody.appendChild(CreateWeakHeader("Week " + week));
}
var td = document.createElement('td');
td.classList.add("ui-droppable");
// Set the value of the cell to a clone of the data, if it's an HTMLElement
// Otherwise, make it a text node.
var value = data[j] instanceof HTMLElement ?
data[j].cloneNode(true) :
document.createTextNode(data[j]);
td.appendChild(value);
tre.appendChild(td);
}
// If the number of data elements is not evenly divisible by 7,
// the remainder will be on the row variable, but not appended
// to the tbody, so do that.
if (tre.querySelectorAll('td').length) {
tbody.appendChild(tre.cloneNode(true));
}
header3.appendChild(tbe);
document.body.appendChild(header);
}
$("#tb").click(function() {
var header = document.createElement("div");
header.innerHTML = "test";
var d = [header, header, header, header, header, header, header, header];
htmlTable(d, days);
});
var days = ['Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag', 'Zondag'];
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="tb">CreateTable</button>

How to remove an entire table using javascript?

I have a calendar table, that shows the entire month's date, if user chose to see next month or previous I need to delete the entire table and replace the new table in that same place, at the moment each table is loading underneath the other because I cant get this to work.
I need to remove table from calendar-dates. but I had no luck. I have used removechild("tb") but didnt work, I also tried var test = document.getElementById("calendarDates");
test.removeChild(test.childNodes[0]);
Here is the code for the table:
document.getElementById("calendar-dates").appendChild(calendar);
Table:
//add calendar table
function get_calendar(day_no, days, m , y){
var table = document.createElement('table');
table.id = "tb";
var tr = document.createElement('tr');
//row for the day letters
for(var c=0; c<=6; c++){
var td = document.createElement('td');
td.innerHTML = "SMTWTFS"[c];
tr.appendChild(td);
}
table.appendChild(tr);
//create 2nd row
tr = document.createElement('tr');
var c;
for(c=0; c<=6; c++){
if(c == day_no){
break;
}
var td = document.createElement('td');
td.innerHTML = "";
tr.appendChild(td);
}
var count = 1;
for(; c<=6; c++){
var td = document.createElement('td');
td.innerHTML = count;
td.style.cursor = "pointer";
td.id = count;
td.onclick = function () {
m = m + 1;
document.getElementById("cDD").value = this.id + "/" + m + "/" + y;
document.getElementById("calendar-container").style.display = "none";
};
count++;
tr.appendChild(td);
}
table.appendChild(tr);
//rest of the date rows
for(var r=3; r<=7; r++){
tr = document.createElement('tr');
for(var c=0; c<=6; c++){
if(count > days){
table.appendChild(tr);
return table;
}
var td = document.createElement('td');
td.innerHTML = count;
td.style.cursor = "pointer";
td.id = count;
td.onclick = function () {
m = m + 1;
document.getElementById("cDD").value = this.id + "/" + m + "/" + y;
document.getElementById("calendar-container").style.display = "none";
};
count++;
tr.appendChild(td);
}
table.appendChild(tr);
}
return table;
}
The removeChild method takes a node, not an ID.
test.removeChild(test.childNodes[0]); probably doesn't work because you have some text nodes before the table.
test.removeChild(test.firstElementChild)probably will work
document.getElementById("calendar-dates").removeChild(document.getElementById('tb'))
document.querySelector('button').addEventListener('click', () => {
document.getElementById('wrapper').removeChild(document.querySelector('table'));
})
table, th, td {
border: 1px solid red;
padding: 2px
}
<div id="wrapper">
<table>
<tr>
<td>Table</td>
<td>Content</td>
</tr>
</table>
</div>
<button>Remove table</button>
Does #calendar-dates contains other html than tables? If not, you can set innerHtml to empty
var calendarDates = document.getElementById("calendar-dates");
calendarDates.innerHtml = '';
calendarDates.appendChild(calendar);

Memory game board creation, javascript

Im trying to make a memory game in javascript, but im having problems with creating the board + adding an event handler(click) to the images that are going in the table data. heres the code snippet:
var board = document.getElementById("board");
var img = document.createElement("img");
var NUM_ROWS = 6;
var NUM_COLS = 6;
for (row = 0; row < NUM_ROWS; row++) {
var tr = document.createElement("tr");
for (col = 0; col < NUM_COLS; col++) {
var td = document.createElement("td");
var img = document.createElement("img");
tr.appendChild(td);
img.src = 'images/image0.png';
tr.appendChild(img);
}
board.appendChild(tr);
}
There are many ways to do this. One way that gives you a lot of flexibility is to build up a string version of the image element that has all the features that you need and insert it into your table cell element by setting td.innerHTML as follows:
function myclick(row,col) {
// handle the click here
}
var board = document.getElementById("board");
var NUM_ROWS = 6;
var NUM_COLS = 6;
for (var row = 0; row < NUM_ROWS; row++) {
var tr = document.createElement("tr");
for (col = 0; col < NUM_COLS; col++) {
var td = document.createElement("td");
var src = "images/image0.png";
var img = '<img src="'+src+'" onclick="myclick('+row+','+col+');">';
td.innerHTML = img;
tr.appendChild(td);
}
board.appendChild(tr);
}
In this case, the img element is created with the onclick function built in and will provide the row and column of the click to your click handling function.

How to check value of table td?

I am trying to create mine field game. "I am very new to Js".
What I have done so far:
var level = prompt("Choose Level: easy, medium, hard");
if (level === "easy") {
level = 3;
} else if (level === "medium") {
level = 6;
} else if (level === "hard") {
level = 9;
}
var body = document.getElementsByTagName("body")[0];
var tbl = document.createElement("table");
var tblBody = document.createElement("tbody");
for (var i = 1; i <= 10; i++) {
var row = document.createElement("tr");
document.write("<br/>");
for (var x = 1; x <= 10; x++) {
var j = Math.floor(Math.random() * 12 + 1);
if (j < level) {
j = "mined";
} else {
j = "clear";
}
var cell = document.createElement("td");
var cellText = document.createTextNode(j + " ");
cell.appendChild(cellText);
row.appendChild(cell);
}
tblBody.appendChild(row);
}
tbl.appendChild(tblBody);
body.appendChild(tbl);
tbl.setAttribute("border", "2");
So I create here 2d table and enter 2 random values in rows and columns (mined or clear).
Where I am stuck is:
Check if td = mined it dies otherwise open the box(td) etc.
How do I assign value of td? I mean how can I check which value(mined/clear) there is in the td which is clicked?
Ps: Please don't write the whole code:) just show me the track please:)
Thnx for the answers!
Ok! I came this far.. But if I click on row it gives sometimes clear even if I click on mined row or vice versa!
// create the table
var body = document.getElementsByTagName("body")[0];
var tbl = document.createElement("table");
tbl.setAttribute('id','myTable');
var tblBody = document.createElement("tbody");
//Create 2d table with mined/clear
for(var i=1;i<=10;i++)
{
var row = document.createElement("tr");
document.write("<br/>" );
for(var x=1;x<=10;x++)
{
var j=Math.floor(Math.random()*12+1);
if(j<level)
{
j = "mined";
}
else{
j = "clear";
}
var cell = document.createElement("td");
var cellText = document.createTextNode(j + "");
cell.appendChild(cellText);
row.appendChild(cell);
}
tblBody.appendChild(row);
}
tbl.appendChild(tblBody);
body.appendChild(tbl);
tbl.setAttribute("border", "2");
//Check which row is clicked
window.onload = addRowHandlers;
function addRowHandlers() {
var table = document.getElementById("myTable");
var rows = table.getElementsByTagName("tr");
for (i = 0; i < rows.length; i++) {
var currentRow = table.rows[i];
var createClickHandler =
function(row)
{
return function() {
var cell = row.getElementsByTagName("td")[0];
var id = cell.innerHTML;
if(id === "mined")
{
alert("You died");
}else
{
alert("clear");
}
};
}
currentRow.onclick = createClickHandler(currentRow);
}
}
I think I do something wrong with giving the table id "myTable"..
Can you see it?
Thank you in advance!
So, the idea would be:
assign a click event to each td cell:
td.addEventListener('click', mycallback, false);
in the event handler (callback), check the content of the td:
function mycallback(e) { /*e.target is the td; check td.innerText;*/ }
Pedagogic resources:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td?redirectlocale=en-US&redirectslug=HTML%2FElement%2Ftd
https://developer.mozilla.org/en-US/docs/DOM/EventTarget.addEventListener
JavaScript, getting value of a td with id name

rowIndex when creating a table with Javascript

I have the following function to append rows and cells to an empty table:
function createTable(size) {
var table = document.getElementById("gameTable");
for (var i=0; i<size; i++) {
var tr = document.createElement("tr");
for (var j=0; j<size; j++) {
var td = document.createElement("td");
tr.appendChild(td);
}
table.appendChild(tr);
tr.rowIndex = i;
}
}
So far so good.
My problem is that later, when I tried to reach specific cells inside the table:
var x = target.parentNode.rowIndex;
var y = target.cellIndex;
table.rows[x].cells[y].innerHTML = 'blah'
target is the specific TD that was clicked.
the rows[x] index is always -1. Every time I try the line above I get an error: "cannot read property 'cells' of undefined"
I even tried manually setting the rowIndex of each Row to what it should be (inside the function), but to no avail.
The cellIndex comes out fine, but the rowIndex is -1 and each and every one of the newly created table rows.
What can I do to correct this?
This can be solved by appending the <tr> elements into a <tbody>.
function createTable(size) {
var table = document.getElementById("gameTable");
var tb = document.createElement("tbody");
for (var i=0; i<size; i++) {
var tr = document.createElement("tr");
for (var j=0; j<size; j++) {
var td = document.createElement("td");
tr.appendChild(td);
}
tb.appendChild(tr);
}
table.appendChild(tb);
}

Categories