Why I cannot replace innerHTML in this case - javascript

Something in the TD innerHTML content prevents it from being replaced see https://jsfiddle.net/ot8vfwc0/
How to force it to be replaced programmatically even if there is that kind of hidden weird characters ?
<table>
<thead>
<tr>
<th scope="col" colspan="1">TITLE</th>
</tr>
<tr>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tbody>
<tr>
<td><br>WEIRD
DO NOT WANT TO BE REPLACED</td>
</tr>
</tbody>
</table>
script:
var myTable = document.getElementsByTagName('table')[0];
var myTbody = myTable.getElementsByTagName('tbody')[0];
_tr = myThead.getElementsByTagName("TR")[0];
_td = _tr.getElementsByTagName("TD")[0];
_th.innerHTML = "TEXT REPLACED";

This is some pretty weird 1998 JavaScript element extraction. Not to mention you're allocating so many vars you're clearly forgetting which ones you defined.
Simplify this with modern JS instead:
var td = document.querySelectorAll("table tbody tr td")[0];
td.textContent="new text";
This gets all <td> elements part of a table→tbody→tr→td chain, we pick the first one, then we set its new content. as text, not as HTML, because that would be silly and a potential security risk if the content comes from anything "not hard-coded".
If we want to add DOM elements in it, we'd use document.createElement(...) and td.appendChild(...) of course:
// find and clear the element
var td = document.querySelectorAll("table tbody tr td")[0];
td.textContent='';
// form new content and add it in
var p = document.createElement("p");
p = "check me out, I'm a paragraph";
td.appendChild(p);
Keep it simple: use modern JavaScript. It got quite a bit simpler in the last 17 years.

Try this:
var myTable = document.getElementsByTagName('table')[0];
var myTbody = myTable.getElementsByTagName('tbody')[0];
_tr = myTbody.getElementsByTagName("TR")[0];
_td = _tr.getElementsByTagName("TD")[0];
_td.innerHTML = "TEXT REPLACED";
Replace myThead with myTbody and _th with _td.

myThead and _th are undefined. Replace them with myTbody and _td and it will work.

Related

Delete all rows in an HTML table except for header with JS

So I am having trouble deleting all of the data in an HTML table with js WITHOUT deleting the header. Here is my HTML:
<html>
<title>Z80 Opcodes</title>
<body>
<input type="text" id = "input" value = "">
<button onClick = "hex()">Hex</button>
<button onClick = "bin()">Bin</button>
<button onClick = "assem()">Assembly</button>
<button onClick = "find()">Find</button>
<table id = "out" style="width:100%">
<thead>
<th align="left">Binary</th>
<th align="left">Hex</th>
<th align="left">Assembly</th>
<th align="left">Description</th>
</thead>
<tbody id="tb">
</tbody>
<script src = "js/script.js">
</script>
</body>
</html>
And here is script.js:
var id = document.getElementById("out");
var ab = "";
var row;
var table = ['0000000000nopno operation', '0000000101ld (bc), **loads ** into BC'];
var bin = ['00000000', '00000001'];
var hex = ['00', '01'];
var assembly = ['nop', 'ld (bc), **'];
var description = ['no operation', 'loads ** into BC'];
l = table.length;
function find() {
row = id.insertRow(0);
for (i=0;i <=l-1;i++) {
ab = table[i];
if (ab.includes(document.getElementById("input").value)) {
row = id.insertRow(-1);
cell1 = row.insertCell(0);
cell2 = row.insertCell(1);
cell3 = row.insertCell(2);
cell4 = row.insertCell(3);
cell1.innerHTML = bin[i];
cell2.innerHTML = hex[i];
cell3.innerHTML = assembly[i];
cell4.innerHTML = description[i];
}
}
}
I have omitted A LOT of array entries because they contained almost the FULL instruction set of thee z80 microprocessor.
What this code does (basically) is it gets an input from the user and if the array table contains that input then it gets the corresponding values from bin, hex, assembly and description and assigns each a column in the table out, then adds a row with the for the data. However, I cannot seem to find a way to delete all of the rows in tbody before another set of values are appended to the table without deleting thead. I have searched around on the web and found several solutions, none of which worked. They either deleted the thead or caused some kind of error (I'll give examples if you ask). I am using Google Chrome version 63.0.3239.132 web browser to run my code.
As you may be able to see I am quite new to js and HTML
Any ideas what I have done wrong?
~Jachdich
First You have to close your <table> tag </table>
This is how you can clear your table.
$('#remove').on('click', ()=>{
$('#tb').empty()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id = "out" style="width:100%">
<thead>
<th align="left">Binary</th>
<th align="left">Hex</th>
<th align="left">Assembly</th>
<th align="left">Description</th>
</thead>
<tbody id="tb">
<tr>
<th>01010101</th>
<th>1231:sdf:sdf42</th>
<th>213123</th>
<th>description</th>
</tr>
</tbody>
</table>
<button id="remove">
clear
</button>
Assuming you want to keep the tbody element intact instead of just removing it and all its children at once:
// get a reference to the tbody element
var tb = document.querySelector('#out tbody');
// while tb has children, remove the first one
while (tb.childNodes.length) {
tb.removeChild(tb.childNodes[0]);
}
// tb is now empty
From a semantic perspective, it would make the removal of rows much easier if you added them to the <tbody> element instead of the <thead> element. This way, you could target the rows within the body and remove them whilst preserving your <thead> (sibling node to ):
var body = document.querySelector('tbody');
while (body.firstChild) {
// This will remove all children within tbody which in your case are <tr> elements
body.removeChild(body.firstChild);
}
body.removeChild(rowsWithinBody)
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody#examples
with jQuery you can do it simply in a single line of code.
$("#table_id tbody tr").remove();
it will remove all rows in a table except the header.

How to add colspan and text in cell?

I'm getting an error when I insert a row and a cell, add a text (innerHTML, textContent) and a colspan. The error reads:
Safari:
"TypeError: Attempted to assign to readonly property."
Chrome:
"Uncaught TypeError: Cannot assign to read only property"
If I remove the text, the colspan will work and any other cells will show; if I remove the colspan, the text will show. If I try to keep both, apart from getting the error, any other cells that exist will disappear, and the colspan won't work.
Example html:
<table id ="my_table">
<thead>
<tr>
<th>text</th>
<th>text</th>
<th>text</th>
<th>text</th>
<th>text</th>
</tr>
Example JS:
function test3() {
//get the table id;
var table = document.getElementById('my_table');
//create row, cell
var my_row = table.insertRow(-1);
var total = my_row.insertCell(0).textContent = "my colspan text";
...or
var total = my_row.insertCell(0).innerHTML = "my colspan text";
...then
total.colSpan = "4";
}
When I searched for this problem, I read that this exists in iOS8 and that it occurs when use in strict mode; however, if I remove "use strict", the error message will disappear, but the problem will persist. Some say it's a webkit bug, but the same thing happens in Firefox, minus the error message.
Possibly related link:
TypeError: Attempted to assign to readonly property. on iOS8 Safari
Am I doing something wrong or is there a workaround?
Addendum: a sub-optimization is to add a second cell that has no text inserted, and give it a colspan.
my_row.insertCell(0).textContent = "my colspan text" doesn't return the cell, it returns the string assigned to textContent
function test3() {
//get the table id;
var table = document.getElementById('my_table');
//create row
var my_row = table.insertRow(-1);
//create cell
var total = my_row.insertCell(0);
//set properties
total.textContent = "my colspan text";
total.colSpan = 4;
}
window.addEventListener('load', test3, false);
<table id="my_table" border="1">
<thead>
<tr>
<th>text</th>
<th>text</th>
<th>text</th>
<th>text</th>
<th>text</th>
</tr>
</thead>
</table>

get all the td elements of tr when clicked

I have a table and when user clicks into a link need to copy the content of that row and populate them into other fields e.g. edit information. How can the row content be populated as an array
<table id='mytable' border='1'>
<thead>
<th id='ID'>ID</th>
<th id='Email'>Email</th>
</thead>
<tr>
<td>1</td>
<td>abc#gmail.com</td>
</tr>
<tr>
<td>2</td>
<td>xyz#gmail.com</td>
</tr>
<tr>
<td>3</td>
<td>pqr#gmail.com</td>
</tr>
</table>
jsfiddle link
http://jsfiddle.net/keJBZ/5/
Not sure why I've answered this one as your question is as vague as it is.
If you want to pull the information from a selected row into an array, here is how you can do it:
http://jsfiddle.net/KyleMuir/keJBZ/6/
var array = new Array();
$('#mytable tr').on('click', copyIntoArray);
function copyIntoArray() {
var self = $(this);
var tds = self.children('td');
array.push(tds[0].innerText, tds[1].innerText);
}
It would make a lot of sense to build up an object to push onto the array so you could have KVP or something similar to provide some context.
EDIT
Here is your fixed version. No need for the array. I also gave your inputs IDs of "email" and "username" for easier selection.
http://jsfiddle.net/KyleMuir/keJBZ/21/
Final code:
$('#mytable tr').on('click', setInformation);
function setInformation() {
$("#edit").show();
var self = $(this);
var tds = self.children('td');
$('#username').val(tds[1].innerText);
$('#email').val(tds[2].innerText);
}
FINAL EDIT?!? turns out FireFox doesn't support .innerText, replaced it with the jQuery to retrieve the values.
http://jsfiddle.net/KyleMuir/keJBZ/24/
This:
$('#username').val(tds[1].innerText);
$('#email').val(tds[2].innerText);
becomes:
$('#username').val($(tds[1]).text());
$('#email').val($(tds[2]).text());
Hope this helps.
Give each row an ID, and then in your JavaScript, use getElementById to get the row which is clicked. Then you can also get all the columns of that row using the same function. You can put all the columns in a var and then use that var to populate whatever you want.

Delete all rows in an HTML table

How can I delete all rows of an HTML table except the <th>'s using Javascript, and without looping through all the rows in the table? I have a very huge table and I don't want to freeze the UI while I'm looping through the rows to delete them
this will remove all the rows:
$("#table_of_items tr").remove();
Keep the <th> row in a <thead> and the other rows in a <tbody> then replace the <tbody> with a new, empty one.
i.e.
var new_tbody = document.createElement('tbody');
populate_with_new_rows(new_tbody);
old_tbody.parentNode.replaceChild(new_tbody, old_tbody)
Very crude, but this also works:
var Table = document.getElementById("mytable");
Table.innerHTML = "";
Points to note, on the Watch out for common mistakes:
If your start index is 0 (or some index from begin), then, the correct code is:
var tableHeaderRowCount = 1;
var table = document.getElementById('WRITE_YOUR_HTML_TABLE_NAME_HERE');
var rowCount = table.rows.length;
for (var i = tableHeaderRowCount; i < rowCount; i++) {
table.deleteRow(tableHeaderRowCount);
}
NOTES
1. the argument for deleteRow is fixed
this is required since as we delete a row, the number of rows decrease.
i.e; by the time i reaches (rows.length - 1), or even before that row is already deleted, so you will have some error/exception (or a silent one).
2. the rowCount is taken before the for loop starts
since as we delete the "table.rows.length" will keep on changing, so again you have some issue, that only odd or even rows only gets deleted.
Hope that helps.
This is an old question, however I recently had a similar issue.
I wrote this code to solve it:
var elmtTable = document.getElementById('TABLE_ID_HERE');
var tableRows = elmtTable.getElementsByTagName('tr');
var rowCount = tableRows.length;
for (var x=rowCount-1; x>0; x--) {
elmtTable.removeChild(tableRows[x]);
}
That will remove all rows, except the first.
Cheers!
If you can declare an ID for tbody you can simply run this function:
var node = document.getElementById("tablebody");
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
Assuming you have just one table so you can reference it with just the type.
If you don't want to delete the headers:
$("tbody").children().remove()
otherwise:
$("table").children().remove()
hope it helps!
I needed to delete all rows except the first and solution posted by #strat but that resulted in uncaught exception (referencing Node in context where it does not exist). The following worked for me.
var myTable = document.getElementById("myTable");
var rowCount = myTable.rows.length;
for (var x=rowCount-1; x>0; x--) {
myTable.deleteRow(x);
}
the give below code works great.
It removes all rows except header row. So this code really t
$("#Your_Table tr>td").remove();
this would work iteration deletetion in HTML table in native
document.querySelectorAll("table tbody tr").forEach(function(e){e.remove()})
Assing some id to tbody tag. i.e. . After this, the following line should retain the table header/footer and remove all the rows.
document.getElementById("yourID").innerHTML="";
And, if you want the entire table (header/rows/footer) to wipe out, then set the id at table level i.e.
How about this:
When the page first loads, do this:
var myTable = document.getElementById("myTable");
myTable.oldHTML=myTable.innerHTML;
Then when you want to clear the table:
myTable.innerHTML=myTable.oldHTML;
The result will be your header row(s) if that's all you started with, the performance is dramatically faster than looping.
If you do not want to remove th and just want to remove the rows inside, this is working perfectly.
var tb = document.getElementById('tableId');
while(tb.rows.length > 1) {
tb.deleteRow(1);
}
Pure javascript, no loops and preserving headers:
function restartTable(){
const tbody = document.getElementById("tblDetail").getElementsByTagName('tbody')[0];
tbody.innerHTML = "";
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<table id="tblDetail" class="table table-bordered table-hover table-ligth table-sm table-striped">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 2</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
a
</td>
<td>
b
</td>
<td>
c
</td>
<td>
d
</td>
</tr>
<tr>
<td>
1
</td>
<td>
2
</td>
<td>
3
</td>
<td>
4
</td>
<tr>
<td>
e
</td>
<td>
f
</td>
<td>
g
</td>
<td>
h
</td>
</tr>
</tr>
</tbody>
</table>
<button type="button" onclick="restartTable()">restart table</button>
If you have far fewer <th> rows than non-<th> rows, you could collect all the <th> rows into a string, remove the entire table, and then write <table>thstring</table> where the table used to be.
EDIT: Where, obviously, "thstring" is the html for all of the rows of <th>s.
This works in IE without even having to declare a var for the table and will delete all rows:
for(var i = 0; i < resultsTable.rows.length;)
{
resultsTable.deleteRow(i);
}
this is a simple code I just wrote to solve this, without removing the header row (first one).
var Tbl = document.getElementById('tblId');
while(Tbl.childNodes.length>2){Tbl.removeChild(Tbl.lastChild);}
Hope it works for you!!.
Assign an id or a class for your tbody.
document.querySelector("#tbodyId").remove();
document.querySelectorAll(".tbodyClass").remove();
You can name your id or class how you want, not necessarily #tbodyId or .tbodyClass.
#lkan's answer worked for me, however to leave the first row, change
from
for (var x=rowCount-1; x>0; x--)
to
for (var x=rowCount-1; x>1; x--)
Full code:
var myTable = document.getElementById("myTable");
var rowCount = myTable.rows.length;
for (var x=rowCount-1; x>1; x--) {
myTable.deleteRow(x);
}
This will remove all of the rows except the <th>:
document.querySelectorAll("td").forEach(function (data) {
data.parentNode.remove();
});
Same thing I faced. So I come up with the solution by which you don't have to Unset the heading of table only remove the data..
<script>
var tablebody =document.getElementById('myTableBody');
tablebody.innerHTML = "";
</script>
<table>
<thead>
</thead>
<tbody id='myTableBody'>
</tbody>
</table>
Try this out will work properly...
Assuming the <table> element is accessible (e.g. by id), you can select the table body child node and then remove each child until no more remain. If you have structured your HTML table properly, namely with table headers in the <thead> element, this will only remove the table rows.
We use lastElementChild to preserve all non-element (namely #text nodes and ) children of the parent (but not their descendants). See this SO answer for a more general example, as well as an analysis of various methods to remove all of an element's children.
const tableEl = document.getElementById('my-table');
const tableBodyEl = tableEl.querySelector('tbody');
// or, directly get the <tbody> element if its id is known
// const tableBodyEl = document.getElementById('table-rows');
while (tableBodyEl.lastElementChild) {
tableBodyEl.removeChild(tableBodyEl.lastElementChild);
}
<table id="my-table">
<thead>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
</thead>
<tbody id="table-rows">
<tr>
<td>Apple</td>
<td>Red</td>
</tr>
<!-- comment child preserved -->
text child preserved
<tr>
<td>Banana</td>
<td>Yellow</td>
</tr>
<tr>
<td>Plum</td>
<td>Purple</td>
</tr>
</tbody>
</table>
Just Clear the table body.
$("#tblbody").html("");
const table = document.querySelector('table');
table.innerHTML === ' ' ? null : table.innerHTML = ' ';
The above code worked fine for me. It checks to see if the table contains any data and then clears everything including the header.

Append tr in table in IE

I have a table structure:
<table id="tableId">
<tbody id="tbodyId">
<tr id="trId1">
<td>id</td><td>name</td>
</tr>
</tbody>
</table>
I am adding new row with simple Javascript like this:
var itemsContainer = dojo.byId('tbodyId');
itemCount++; //it will give id to tr i.e. trId2
var newItemNode = document.createElement('tr');
newItemNode.setAttribute("id", 'trId' + itemCount);
newItemNode.innerHTML ='<td>id</td><td>anotherName</td>';
itemsContainer.appendChild(newItemNode);
All works fine in Firefox but row is not appended in IE. New table after it in Firefox becomes:
<table id="tableId">
<tbody id="tbodyId">
<tr id="trId1">
<td>id</td><td>name</td>
</tr>
<tr id="trId2">
<td>id</td><td>anotherName</td>
</tr>
</tbody>
</table>
I saw other codes and help. I only want one tbody in this table with simple Javascript no jQuery.
There are special functions for creating table cells ( and rows ) eg - insertRow for rows and insertCell for cells - it works in all browsers
var newItemNode = itemsContainer.insertRow( itemsContainer.rows.length - 1 );
newItemNode.setAttribute("id", 'trId' + itemCount);
var cell = newItemNode.insertCell( 0 );
cell.innerHTML = 'id';
...
PS. I think DOJO Framework have something for inserting rows and cells
First off, this jsfiddle works fine in FF6 & IE8
Make sure that your real html has the proper markup. Your example shows a closing tbody element without the slash
<tr id="trId2">
<td>id</td><td>anotherName</td>
</tr>
<tbody> <!-- This line should be </tbody> -->
IE is inconsistant with its acceptance of bad markup.
In addition, code like this:
var newItemNode = document.createElement('tr');
newItemNode.setAttribute("id", 'trId' + itemCount);
newItemNode.innerHTML ='<td>id</td><td>anotherName</td>';
Is exactly the sort of code that toolkits like dojo (and its smarter cousin, jQuery) are built to avoid. I suspect the code for creating a new row are different in the version of IE you're testing on.
try this
<html>
<script language = "javascript">
function kk()
{
var itemsContainer = document.getElementById("tbodyId");
var newItemNode = document.createElement('tr');
newItemNode.setAttribute("id", 'trId' + 1);
var newCellItem1 = document.createElement('td');
newCellItem1.innerHTML = "id";
var newCellItem2 = document.createElement('td');
newCellItem2.innerHTML = "anotherName";
newItemNode.appendChild(newCellItem1);
newItemNode.appendChild(newCellItem2);
itemsContainer.appendChild(newItemNode);
}
</script>
<table id="tableId">
<tbody id="tbodyId">
<tr id="trId1">
<td>id</td><td>name</td>
</tr>
</tbody>
</table>
<input type="button" value = "heihei" onclick = "kk();"></input>
</html>

Categories