Preserve HTML table location after dynamic update - javascript

When I update an HTML table using appendChild(), the entire table is moved to the bottom of the document. How do I preserve the location of the table in the DOM?
My example is also posted on JSFiddle.
<!--I want the existing table below to stay fixed in place after new rows are added.-->
<table id="table">
<tr>
<td> Table Cell 1</td>
<td> Table Cell 2</td>
</tr>
</table>
<!--The following button will add rows, but also move the table. How do I stop the move?-->
<input type="button" value="ADD NEW ROWS." onclick="generate_table()">
<script>
// This function just creates new rows for the table
function generate_table() {
var body = document.getElementsByTagName("body")[0];
var tbl = document.getElementById("table");
var tblBody = document.createElement("tbody");
for (var i = 0; i < 2; i++) {
var row = document.createElement("tr");
for (var j = 0; j < 2; j++) {
var cell = document.createElement("td");
var cellText = document.createTextNode("cell " + i + ", column " + j);
cell.appendChild(cellText);
row.appendChild(cell);
}
tblBody.appendChild(row);
}
tbl.appendChild(tblBody);
body.appendChild(tbl);
}
</script>
<style>
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
</style>

Remove the following line, you don't need it.
body.appendChild(tbl);
The table node is already a part of the Document Object Model, you don't need to add it again. By appending the element to body, you are moving it from the current position to the end of the body node.
As a rule of thumb, you need to use appendChild, only if the element was created dynamically using createElement.

Related

JavaScript Restart Counter

I am probably overthinking the question, but how do I restart a counter? Also, as you will see in my code, the counter is supposed to match but doesn't. I want the cell to have a shared value of the row that it is in, for example the first rows cells should have the ID: cell 0.0, cell 0.1, but rather it has skipped one where the first number is one row ahead.
var rowCount = 0;
var cellCount = 0;
function appendRow(id, style) {
var table = document.getElementById(id); // table reference
length = table.length,
row = table.insertRow(table.rows.length); // append table row
row.setAttribute('id', style);
var i;
row.id = 'row' + rowCount;
rowCount++
console.log(rowCount, cellCount);
// insert table cells to the new row
for (i = 0; i < table.rows[0].cells.length; i++) {
createCell(row.insertCell(i), i, 'cell ' + rowCount + '.' + cellCount); // doesn't start over once row changes
cellCount++
}
}
function createCell(cell, text, style) {
var div = document.createElement('div'), // create DIV element
txt = document.createTextNode('_'); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('id', style); // set DIV class attribute
div.setAttribute('idName', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}
table {
text-align: center;
}
td {
width: 100px;
}
<button id="addCust" class="addSort" onclick="appendRow('custList')">add customer</button>
<div class="custScroll">
<table id="custListTop" contenteditable="false">
<tr>
<td style="border-top-left-radius: 5px;">Customers</td>
<td style="border-top-right-radius: 5px;">Main Location</td>
</tr>
</table>
<table id="custList" contenteditable="true">
<tr>
<td>Someone</td>
<td>something</td>
</tr>
</table>
</div>
I'm not sure this is what you want, but if you put rowCount++ after the for loop it starts off the first element at 0 then increments from there.
If you want the cells to start over then change createCell to use i instead of cellCount:
createCell(row.insertCell(i), i, 'cell ' + rowCount + '.' + i);

Add table header for dynamic table in javascript

I'm trying to create a table in javascript and put a header on it. I tried to incorporate the answer from this SO question but perhaps I didn't include it in the right place. The body of the table works perfectly, but the header appends as a bunch of text to the top instead of a nicely formatted header. Here is the code:
function generate_table() {
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
//var header = document.createElement("header");
var header = '<tr><th>Country</th><th>City</th></tr>';
//var header = "<th>Header</th>";
var tblBody = document.createElement("tbody");
// creating all cells
for (var i = 0; i < results.weak_sent.length; i++) {
// creates a table row
var row = document.createElement("tr");
for (var j = 0; j < 2; j++) {
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var cell = document.createElement("td");
if (j == 0) {
var cellText = document.createTextNode(results.weak_sent_num[i]);
} else {
var cellText = document.createTextNode(results.weak_sent[i]);
}
cell.appendChild(cellText);
row.appendChild(cell);
}
// add the row to the end of the table body
tblBody.appendChild(row);
}
tbl.append(header)
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
}
It prints the rows and the columns correctly, but instead of interpreting the <tr><th> as HTML tags it just prints them out as text. I've also noticed that if the table text contains any HTML tags, like <strong> or <b>, they are returned as plain text as well. How can I make them be read as HTML. I have a CSS page as well but there's no reset or anything (intentionally) affecting the use of bold or tables. Here's my result
<tr><th>Country</th><th>City</th></tr>
1 Row 1 text
2 Row <b>2</b> text
Solution1
The way you are appending tbody rows, you can insert the heading as well. So instead of tbl.append(header) and defining the header string, you can use something like below:
results = {
weak_sent: [
"row 1 data",
"row 2 data"
],
weak_sent_num: [1,2]
}
function generate_table() {
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
//var header = document.createElement("header");
// var header = '<tr><th>Country</th><th>City</th></tr>';
var header= document.createElement('thead')
var headingRow = document.createElement('tr')
var headingCell1 = document.createElement('td')
var headingText1 = document.createTextNode('country')
headingCell1.appendChild(headingText1)
headingRow.appendChild(headingCell1)
var headingCell2 = document.createElement('td')
var headingText2 = document.createTextNode('City')
headingCell2.appendChild(headingText2)
headingRow.appendChild(headingCell2)
header.appendChild(headingRow)
tbl.appendChild(header)
//var header = "<th>Header</th>";
var tblBody = document.createElement("tbody");
// creating all cells
for (var i = 0; i < results.weak_sent.length; i++) {
// creates a table row
var row = document.createElement("tr");
for (var j = 0; j < 2; j++) {
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var cell = document.createElement("td");
if (j == 0) {
var cellText = document.createTextNode(results.weak_sent_num[i]);
} else {
var cellText = document.createTextNode(results.weak_sent[i]);
}
cell.appendChild(cellText);
row.appendChild(cell);
}
// add the row to the end of the table body
tblBody.appendChild(row);
}
// This is for the quick solution
// tbl.innerHTML = header
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
}
generate_table()
Solution2
As a quick solution you can use innerHTML property, as shown below.
results = {
weak_sent: [
"row 1 data",
"row 2 data"
],
weak_sent_num: [1,2]
}
function generate_table() {
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
//var header = document.createElement("header");
var header = '<tr><th>Country</th><th>City</th></tr>';
//var header = "<th>Header</th>";
var tblBody = document.createElement("tbody");
// creating all cells
for (var i = 0; i < results.weak_sent.length; i++) {
// creates a table row
var row = document.createElement("tr");
for (var j = 0; j < 2; j++) {
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var cell = document.createElement("td");
if (j == 0) {
var cellText = document.createTextNode(results.weak_sent_num[i]);
} else {
var cellText = document.createTextNode(results.weak_sent[i]);
}
cell.appendChild(cellText);
row.appendChild(cell);
}
// add the row to the end of the table body
tblBody.appendChild(row);
}
// This is for the quick solution
tbl.innerHTML = header
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
}
generate_table()

Button not rendering where expected

I am clicking a button in my HTML and expecting a table to be created with X amount of rows depending on the for loop and then at the end of each row a button.
I am expecting the output to look like this:
<table>
<tr>
<td> first element </td>
<button> </button>
</tr>
<tr>
<td> first element </td>
<button> </button>
</tr>
</table>
However for some reason the button does not render on the first row:
<table>
<tr>
<td> first element </td>
</tr>
<tr>
<td> first element </td>
<button> </button>
</tr>
</table>
This is the code I am using:
function makeHTMLMatchesTable(array){
var table = document.createElement('table');
var button = document.createElement('button');
button.setAttribute("id", "unMatchButton");
console.log(array.length, 'ARRAY');
for (var i = 0; i < array.length; i++) {
console.log(array[i], 'ai');
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.textContent = array[i];
row.appendChild(cell);
row.appendChild(button);
table.appendChild(row);
}
return table;
}
I am expecting the output to look like this
The structure you quote is invalid. You can't have button as a direct child of tr. From the spec for tr, the only things that can be in a tr element are td, th, or script-supporting elements.
However for some reason the button does not render on the first row:
Because you've only created one button element, and then appended it to two separate rows. Appending it doesn't clone it, it moves it from its old parent (if any) to a new one.
To fix it:
Create a new button each time you want a new button (with a new id; id values must be unique in a document).
Append the button to a td, not to a tr.
Example:
function makeHTMLMatchesTable(array) {
var table = document.createElement('table');
for (var i = 0; i < array.length; i++) {
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.textContent = array[i];
row.appendChild(cell);
cell = document.createElement('td'); // Second td
var button = document.createElement('button'); // New button for each
button.setAttribute("id", "unMatchButton" + i); // Unique id
cell.appendChild(button); // Button in cell
row.appendChild(cell); // Add second cell
table.appendChild(row);
}
return table;
}
document.body.appendChild(
makeHTMLMatchesTable(["one", "two", "three"])
);
you need to create a new button for each row
function makeHTMLMatchesTable(array){
var table = document.createElement('table');
console.log(array.length, 'ARRAY');
for (var i = 0; i < array.length; i++) {
console.log(array[i], 'ai');
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.textContent = array[i];
var button = document.createElement('button');
button.setAttribute("id", "unMatchButton");
row.appendChild(cell);
row.appendChild(button);
table.appendChild(row);
}
return table;
}

Changing a div space with a table

Suppose I have these three spaces that are blank to start with. I want to change using innerHTML in JavaScript.
<p id="topname"></p>
<div id="table"></div>
<p id="botname"></p>
document.getElementById("topname").innerHTML = "Boy";
document.getElementById("botname").innerHTML = "Girl";
I managed to change topname and botname with the innerHTML. How do I change div id="table" to display an x by y (2x2, 4x4, 8x8,etc.) table?
Instead of replacing the <div> with a <table>, it is recommended to create a <table> as a child node of the <div> As long as you have not added additional styling to the <div> (like padding or margins), this will have no effect on the display.
A couple of loops to build <tr> and <td> will do the job. Here's a function that takes x and y:
function makeTable(rows, cols) {
// Create a table node
var tbl = document.createElement('table');
// Make a <tr> for each row
for (var i=0; i<rows; i++) {
var tr = document.createElement('tr');
// And make a <td> for eah col
for (var j=0; j<cols; j++) {
var td = document.createElement('td');
// Append them to the current tr
tr.appendChild(td);
}
// Append the row
tbl.appendChild(tr);
}
return tbl;
}
// Create a new 2x4 table with the function
var newTable = makeTable(2, 4);
// And append it as a child to the <div id='table'>
document.getElementById('table').appendChild(newTable);
Here it is in action
You should be able to do it the same way, however, that div id might be giving you issues. TABLE is an html entity unto itself. I would rename that.
document.getElementById("table").innerHTML = "<table><caption>Caption</caption><thead>Table Header</thead><tfoot>Table Footer</tfoot><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody></table>";
And what Shadow Wizard said above. It is best to use the right tool for the job. My answer is solely if you insist on doing it within a div.
First of all, change your div to a table manually:
<table id="table"></table>
With following code you can fill your table with rows and columns:
document.getElementById("table").appendChild(makeTable(2, 4));
function makeTable(rows, cols) {
var table = document.createDocumentFragment(), tr = document.createElement("tr"), td = document.createElement("td"), i, j;
for(j = 0; j < cols; j++) tr.appenChild(td.cloneNode(true));
for(i = 0; i < rows; i++) table.appendChild(tr.cloneNode(true));
return table;
}

Adding rows in HTML table using javascript

I am trying to insert rows into an html table with javascript. I have the table created and can add rows successfully with the click of a button. However, I want to be able to populate the rows with elements from several arrays on load. The button is just to make sure the rows are being added.
<html>
<input type="button" value="Add row" onclick="javascript:appendRow()" class="append_row"/>
<br/><br/></p>
<table id="my_table" align="center" cellspacing="0" cellpadding="0" border="0">
<tr>
<td>Name</td>
<td>Age</td>
<td>Sex</td>
</tr>
</table>
<p></center></p>
<script type="text/javascript" language="javascript">
function appendRow(){
var names = ["Paul", "Mike", "Linda"];
var ages = ["16", "23", "44"];
var male_female = ["M", "M", "F"];
var tbl = document.getElementById('my_table'); // table reference
// append table row
var row = tbl.insertRow(tbl.rows.length);
// insert table cells to the new row
var row = tbl.insertRow();
for(var i=0;i<tbl.rows[0].cells.length;i++)
createCell(row.insertCell(i), i, 'row');
}
function createCell(cell, text, style){
var div = document.createElement('div'); // create DIV element
var txt = document.createTextNode(text); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('class', style); // set DIV class attribute
div.setAttribute('className', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}
</script>
<style>
.row{background-color:#FFD6D6;width:43px;margin:3px;}
.col{background-color:#D6FFD6;width:43px;margin:3px;}
table#my_table{border-collapse:collapse;}
table#my_table td{width:50px;height:27px;border:1px solid #D3D3D3;font- size:10pt;text-align:center;padding:0;}
.append_row{background-color:#FFD6D6;border:1px #ccc solid;}
.append_column{background-color:#D6FFD6;border:1px #ccc solid;}
.delete{background-color:#eee;border:1px #ccc solid;}
</style>
</html>
In your for loop, try something like:
var j = tbl.rows.length - 1;
for (var i=0;i<tbl.rows[0].cells.length;i++) {
var cell_text = '';
if (i == 0) {
cell_text = name[j];
} else if (i == 1) {
cell_text = ages[j];
} else if (i == 2) {
cell_text = male_female[j];
}
createCell(row.insertCell(i), cell_text, 'row');
}
You forgot the "body" tag in the HTML syntax. You can put a call to your function in the onLoad variable, so it will be called after the page with loaded.

Categories