Append tr in table in IE - javascript

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>

Related

how to convert/transform an HTML table tbody (with rowspans) TO json?

I have an HTML table with combined row td's, or how to say, I don't know how to express myself (I am not so good at English), so I show it! This is my table:
<table border="1">
<thead>
<tr>
<th>line</th>
<th>value1</th>
<th>value2</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2">1</td>
<td>1.1</td>
<td>1.2</td>
</tr>
<tr>
<td>1.3</td>
<td>1.4</td>
</tr>
<tr>
<td rowspan="2">2</td>
<td>2.1</td>
<td>2.2</td>
</tr>
<tr>
<td>2.3</td>
<td>2.4</td>
</tr>
</tbody>
</table>
(you can check it here)
I want to convert this table to a JSON variable by jquery or javascript.
How should it look like, and how should I do it? Thank you, if you can help me!
if you want to convert only text use this one :
var array = [];
$('table').find('thead tr').each(function(){
$(this).children('th').each(function(){
array.push($(this).text());
})
}).end().find('tbody tr').each(function(){
$(this).children('td').each(function(){
array.push($(this).text());
})
})
var json = JSON.stringify(array);
To make a somehow representation of your table made no problem to me, but the problem is how to parse it back to HTML! Here a JSON with the first 6 tags:
{"table":{"border":1,"thead":{"th":{"textContent":"line","tr":"textContent":"value1",...}}}}}...
OR for better understanding:
{"tag":"table","border":1,"child":{"tag":"thead","child":{"tag":"th","textContent":"line",
"child":{"tag":"tr","textContent":"value1","child":...}}}}...
Closing tags are included.
For further explanations I need to know whether your table is a string or part of the DOM.
I belive this is what you want:
var jsonTable = {};
// add a new array property named: "columns"
$('table').find('thead tr').each(function() {
jsonTable.columns = $(this).find('th').text();
};
// now add a new array property which contains your rows: "rows"
$('table').find('tbody tr').each(function() {
var row = {};
// add data by colum names derived from "tbody"
for(var i = 0; i < jsonTable.columnsl.length; i++) {
row[ col ] = $(this).find('td').eq( i ).text();
}
// push it all to the results..
jsonTable.rows.push( row );
};
alert(JSON.stringify(jsonTable));
I think there should be some corrections, but this is it I think.

table mapping by th and first td in row to populate from json object

using php to echo json array inline i want js/jquery to populate table according to these data.
HTML table
<table>
<thead>
<tr>
<th>Time</th>
<th data-day='2013-03-15'>15-3</th>
<th data-day='2013-03-16'>16-3</th>
<th data-day='2013-03-17'>17-3</th>
</tr>
</thead>
<tbody>
<tr data-time='09'>
<td>9am</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<script>
var arr=[
{"date":"2013-03-15","id":"4","time_booked":"09:00:00"},
{"date":"2013-03-15","id":"1","time_booked":"09:10:00"},
{"date":"2013-03-17","id":"5","time_booked":"09:30:00"}
];
$.each(arr,function(){
console.log('id:'+this.id+'inside:'+this.date+'|'+this.time_booked);
});
</script>
i want to loop thro arr and according to its date and time_booked write id inside td.
for example first row will go to td with date-day='2013-03-15' and data-time='09'
so how can i do this using javascript ?
im thinking should i include data-day,data-time inside each td in tbody ? or is there a better way to do it ?
current approach:
include data-day inside each tr so html of tbody is
<tr data-time='09'>
<td data-day='2013-03-15'></td>
<td data-day='2013-03-16'></td>
etc..
</tr>
then use js
$.each(arr,function(){
var rday=this.date;
var rtime=this.time_booked;
var sel='tr[data-hr="'+rtime.substr(0,2)+'"]';
var dom=$(sel).find('td[data-day="'+rday+'"]').first();
if(dom.length)dom.append(this.id);
});
but i have a feeling its stupid ! there must be a way to map table using x,y (table head,row head) or there is none ?
I think the jQuery index function is what you're looking for. In the code sample below, I've used it to fetch the colIndex for the date. In this case, it fetches all of the th cells within the table, and uses .index(..) with a selector seeking the required date. This gives the column index of the date you're seeking, and from there it's all pretty straight-forward.
var arr=[
{"date":"2013-03-15","id":"4","time_booked":"0900"},
{"date":"2013-03-15","id":"1","time_booked":"0910"},
{"date":"2013-03-17","id":"5","time_booked":"0930"}
];
$.each(arr,function(){
var cell = GetCellByDateAndTime(this.date, this.time_booked);
$(cell).text(this.id);
});
function GetCellByDateAndTime(date, time) {
var colIndex = $("#BookingsTable th").index($("[data-day='" + date + "']"));
var row = $("#BookingsTable tr[data-time='" + time + "']")
var cell = $(row).children($("td"))[colIndex];
return cell;
}
And a Fiddle.

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.

Can't set innerHTML on tbody in IE

I have a table like this:
<table>
<thead>
<tr>
<th colspan="1">a</th>
<th colspan="3">b</th>
</tr>
</thead>
<tbody id="replaceMe">
<tr>
<td>data 1</td>
<td>data 2</td>
<td>data 3</td>
<td>data 4</td>
</tr>
</tbody>
</table>
and a method returns me the following after an ajax request:
<tr>
<td>data 1 new</td>
<td>data 2 new</td>
<td>data 3 new</td>
<td>data 4 new</td>
</tr>
I want to change the innerHTML like
document.getElementById('replaceMe').innerHTML = data.responseText;
However, it seems that IE can't set innerHTML on <tbody>. Can anyone help me with a simple workaround for this issue?
That is true, innerHTML on tbody elements is readOnly in IE
The property is read/write for all
objects except the following, for
which it is read-only: COL, COLGROUP,
FRAMESET, HEAD, HTML, STYLE, TABLE,
TBODY, TFOOT, THEAD, TITLE, TR.
source: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
You can do something like this to work around it:
function setTBodyInnerHTML(tbody, html) {
var temp = tbody.ownerDocument.createElement('div');
temp.innerHTML = '<table>' + html + '</table>';
tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody);
}
Basically it creates a temporary node into which you inject a full table. Then it replaces the tbody with the tbody from the injected table. If it proves to be slow, you could make it faster by caching temp instead of creating it each time.
Create a temp node to store a table in, then copy them to the tbody
var tempNode = document.createElement('div');
tempNode.innerHTML = "<table>" + responseText+ "</table>";
var tempTable = tempNode.firstChild;
var tbody = // get a reference to the tbody
for (var i=0, tr; tr = tempTable.rows[i]; i++) {
tbody.appendChild(tr);
}
Both the answers above seem a bit unclear. Plus, the created div is never removed, so calling those functions repeatedly eats memory. Try this:
// this function must come before calling it to properly set “temp”
function MSIEsetTBodyInnerHTML(tbody, html) { //fix MS Internet Exploder’s lameness
var temp = MSIEsetTBodyInnerHTML.temp;
temp.innerHTML = '<table><tbody>' + html + '</tbody></table>';
tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody); }
MSIEsetTBodyInnerHTML.temp = document.createElement('div');
if (navigator && navigator.userAgent.match( /MSIE/i ))
MSIEsetTBodyInnerHTML(tbody, html);
else //by specs, you can not use “innerHTML” until after the page is fully loaded
tbody.innerHTML=html;
Even with this code, though, MSIE does not seem to properly re-size the table cells in my application, but I'm filling an empty tbody tag with variable generated content, while the thead cells' colspan values are set to a fixed value: the maximum number of cells that may be in the generated tbody. While the table tbody is 50 cells wide, only two columns show. Perhaps if the table was originally filled, and the cells were replaced with the same internal structure, this method would work. Google's Chrome does an excellent job of rebuilding the table, while Opera's desktop browser can resize to more columns just fine, but if you remove columns, the remaining column widths remain as narrow as they were; however with Opera, by hiding the table (display=none) then re-showing it (display=table), the generated table tbody cells then size properly. I've given up with Firefox. It's the MSIE-6 of 2012 - a nightmare to develop for which must have additional markup added just to make HTML-CSS layouts work because it does not conform to standards that even MSIE now does. So I haven't tested the tbody.innerHTML workings in Firefox.
This can be fixed by creating a shim/polyfill for .innerHTML. This could get you (you, dear reader) started:
if (/(msie|trident)/i.test(navigator.userAgent)) {
var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
get: function () {return innerhtml_get.call (this)},
set: function(new_html) {
var childNodes = this.childNodes
for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
this.removeChild (childNodes[0])
}
innerhtml_set.call (this, new_html)
}
})
}
var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)
document.body.innerHTML = ""
console.log (mydiv.innerHTML)
http://jsfiddle.net/DLLbc/9/
<table id="table">
<thead>
<tr>
<th colspan="1">a</th>
<th colspan="3">b</th>
</tr>
</thead>
<tbody id="replaceMe">
<tr>
<td>data 1</td>
<td>data 2</td>
<td>data 3</td>
<td>data 4</td>
</tr>
</tbody>
</table>
<button type="button" onclick="replaceTbody()">replaceTbody</button>
<script>
function $(id){
return document.getElementById(id);
}
function replaceTbody(){
var table = $('table');
table.removeChild($('replaceMe'));
var tbody = document.createElement("tbody");
tbody.setAttribute("id","replaceMe");
table.appendChild(tbody);
var tr = document.createElement('tr');
for(var i=1;i<5;i++){
var td = document.createElement('td');
td.innerHTML = 'newData' + i;
tr.appendChild(td);
}
tbody.appendChild(tr);
}
</script>

Rearranging table in JavaScript

I want reorder table rows using JavaScript .
for example take the following dummy table:
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
<td>D1</td>
</tr>
</table>
I want to do this in JavaScript without using jQuery. I want to show the A1,B1,C1,D1.. row as the first row and then 1,2,3,4 row and then A,B,C,D row.
I know that there will be some wait time on the client side but I need to do it in the client side. Is there some generic solution to do this, for any number of rows?
If I understand correctly, you are asking how to take the last row and make it the first row, pushing down the rest. This should do it:
<table id="mytable">
...
</table>
<script type="text/javascript">
var tbl = document.getElementById('mytable');
var rows = tbl.getElementsByTagName('tr');
var firstRow = rows[0];
var lastRow = rows[rows.length];
firstRow.parentNode.insertBefore(lastRow.parentNode.removeChild(lastRow), firstRow);
</script>
Assuming your table does not have nested tables. At which point this would need to be a little smarter. This also assumes you're not using TBODY and THEAD nodes. But I'm sure you can get the idea and enhance it from there.
Do:
var table = ...; // Get reference to table (by ID or other means)
var lastRow = table.rows[table.rows.length - 1];
lastRow.parent.insertBefore(table.rows[0], lastRow);
The best way to solve this in Javascript is:
Give the Tr.. a unique name. for eg: X_Y,X_Z,A_Y,A_Z
Now add a hidden lable or text Box which gives the sorting order from the server i.e When the page renders I want to sort it All the Tr's that have a ID starting with A should come first and All the Z's should come second.
<asp:label id="lblFirstSortOrder" runat="server" style="display:none;">A,X</label>
<asp:label id="lblSecondSortOrder" runat="server" style="display:none;">Z,Y</label>
When the page renders..the order should be A_Z,A_Y,X_Z,X_Y
Before Rendering this is table that comes from the aspx file:
<table>
<tr id='Tr_Heading'>
<td>A</td>
<td>B</td>
</tr>
<tr id="Tr_X_Y">
<td>GH</td>
<td>GH1</td>
</tr>
<tr id="tr_X_Z">
<td>HU</td>
<td>HU1</td>
</tr>
<tr id="tr_A_Z">
<td>JI</td>
<td>JI1</td>
</tr>
<tr id="tr_A_Y">
<td>JI</td>
<td>JI1</td>
</tr>
Script:
function SortAndArrange()
{
var firstList = document.getElementById('lblFirstSortOrder').value;
var secondList = document.getElementById('lblSecondSortOrder').value;
var firstTypes = new Array();
firstTypes = firstList.split(',');
var secondLists = new Array();
secondLists = secondList.split(',');
var refNode = document.getElementById('Tbl_' + firstTypes[0] + "_" + secondTypes[0]);
for (var i = 0; i<firstTypes.length; i++)
{
for (var j = 0; j< secondTypes.length;j++)
{
var TrName = 'Tbl_'+firstTypes[i]+'_'+secondTypes[j];
var FirstSecondTrs = document.getElementById(TrName);
if (FirstSecondTrs)
{
FirstSecondTrs.parentNode.removeChild(FirstSecondTrs);
insertAfter(refNode,FirstSecondTrs);
refNode = FirstSecondTrs;
}
}
}
}
function insertAfter( referenceNode, newNode )
{
referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling );
}
I hope you guys get the idea.. for me the sorting order will always come from the server and not from the user of the page...
Thanks a Lot for all the answers.. Apprecite it. Helped me get to this solution.
Thanks,
Ben

Categories