How to add colspan and text in cell? - javascript

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>

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.

Why I cannot replace innerHTML in this case

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.

Simple show/hide gone wrong in Javascript

I'm trying to create a show/hide function for data within a table populated with data from a mssql database. The function should look for rows with the same value in the "capability" column and onclick, hide all rows with the same value. After this, a row is inserted into the table with the same capability value, but summarizes the data in the hidden rows. This should work in the way that grouping cells together works in excel.
I've managed to get this to work, but it only works for the first click and I receive a "cannot read innerHTML property of NULL" for any of the function's calls after that.
function compactRows(thisrow) {
var totalRows = document.getElementById("DataTable").getElementsByTagName("tr").length;
var summaryVal1= [];
var summaryVal2= [];
for(var i = 1; i < totalRows;i++) {
var trID = "capability" + i;
if(thisrow.innerHTML == document.getElementById(trID).innerHTML) { //The error gets returned on this line
summaryVal1.push(document.getElementById(trID).parentNode.children[5].innerHTML);
summaryVal2.push(document.getElementById(trID).parentNode.children[14].innerHTML);
document.getElementById(trID).parentNode.style.display = 'none';
}
}
createNewRow(thisrow, summaryVal1, summaryVal2);
}
//I took out the logic for the data summarizing in the createNewRow function because I don't think its relevant to the issue I'm having. Also, I didn't want to crowd the area with unrelated code
function createNewRow(row, ibxMobile, overallStatus) {
var table = document.getElementById("DataTable");
var localRow = table.insertRow(row.parentNode.rowIndex);
var cell1 = localRow.insertCell(0);
cell1.setAttribute("id", "entry1");
var cell2 = localRow.insertCell(0);
cell2.setAttribute("id", "Capability");
cell2.innerHTML = row.innerHTML;
var cell3 = localRow.insertCell(0);
cell3.setAttribute("id", "entry3");
}
The function called at the bottom, createNewRow, handles making the row to be entered after all the rows are hidden. It also, handles the logic for summarizing the hidden rows.
All help is greatly appreciated! Thank you
Edit 1: example table set up
<table>
<tr>
<th>Entry1 </th>
<th>Capability</th>
<th>Entry3 </th>
</tr>
<tr>
<td>1.1</td>
<td id="Capability1" onclick="compactRows(this)">Lasers</td>
<td>stuff</td>
</tr>
<tr>
<td>1.2</td>
<td id="Capability2" onclick="compactRows(this)">Lasers</td>
<td>things</td>
</tr>
<tr>
<td>2.1</td>
<td id="Capability3" onclick="compactRows(this)">Beams</td>
<td>more things</td>
</tr>
</table>
//The Below table is what it looks like after clicking either of the first two entries
<table>
<tr>
<th>Entry1 </th>
<th>Capability</th>
<th>Entry3 </th>
</tr>
<tr>
<td>1</td>
<td id="Capability">Lasers</td>
<td></td>
</tr>
<tr>
<td>2.1</td>
<td id="Capability3" onclick="compactRows(this)">Beams</td>
<td>more things</td>
</tr>
</table>
There is no "Capability1" id for any rows after the "CreateNewRow" is called. Therefore, the second time "CompactRows()" is called a null reference is thrown when accessing "document.getElementById("Capability1").innerHTML". Rework the CreateNewRow to inlcude the increment for the Capability id value or test that "getElementById" actually returns an object before attempting to access the innerHTML method.

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.

Hide a column in a javascript populated table

I would like to hide the entire age column on this table.
<table id="displayTable">
<tr>
<td class="Name"></td>
<td class="Phone"></td>
<td class="Age"></td>
</tr>
</table>
Javascript follows to hide Age cell -
var table = document.getElementById('displayTable');
var tableRow = table.getElementsByTagName('tr');
for (var row = 0; row < tableRow.length; row++) {
var cells = tableRow[row].getElementsByTagName('td')
cells[2].style.display='none';
}
error says -
"2.style is null or not an object."
What am I missing?
Well, first of all, check your table id. You have it set to 'displayTable' but you're attempting to look it up by 'displayLossTable'.
When i fix that id, and plug your code into jsFiddle, everything works.
what does alert(cells[2]) give you? Alternatively you should try add/remove class instead of inline styles:
el.className+= 'hide'

Categories