I'm creating an HTML table from a server-side array (google apps script; so tableArray is coming from there). I have two forEach functions which work. However, I'm attempting to use two for loops instead because I'd like to be able to add different classes to different <td>'s.
The output doesn't come out as expected (see #1 below). I can either get an array in one column (instead of each element of the array as a separate <td> or the arrays are repeated in each <td> (see #2 below).
What do I need to change in my for loops to get the expected output?
You can see the version that works HERE.
1 (works with forEach)
2 (does not work with for)
Index.html
function buildTable(tableArray) {
var table = document.getElementById('table');
var tableBody = document.createElement('tbody');
var tbodyID = tableBody.setAttribute('id', 'tbody');
for (var i = 0; i < tableArray.length; ++i) {
var column = tableArray[i];
var colA = column[0];
var colB = column[1];
var colC = column[2];
var colD = column[3];
if (colA != "") {
var row = document.createElement('tr');
for (var j = 0; j < column.length; ++j) {
var cell = document.createElement('td');
cell.appendChild(document.createTextNode(column));
row.appendChild(cell);
}
}
tableBody.appendChild(row);
}
table.appendChild(tableBody);
document.body.appendChild(table);
}
Instead of line cell.appendChild(document.createTextNode(column));
write cell.appendChild(document.createTextNode(column[j]));
You've forgotten to add index [j]
// Loop over rows
for (var i = 0; i < tableArr.length; i++) {
var row = tableArr[i];
// loop over columns
for( var j =0; j<row.length; j++){
//create each column and append to row
}
// append row to table body
}
// append table body to DOM
For performance reasons you want to write to the DOM only once and create the table in memory first.
Change
cell.appendChild(document.createTextNode(column));
to
cell.appendChild(document.createTextNode(column[i]));
This will make it loop through all of your column data properly instead of appending the same content of the whole array repeatedly.
Related
I want to create a table by javascript. It should be a Appointment calender for events. with two rows and two lines per event. In the first line are the datenumber and the kind of event. In the second line are the weekday and the place, where the event are. For the Phase of Development I have only an exemple text. I include my js-file in my html-file but there isn't a table. Can someone check my code because I did not find a mistake
function dates(){
var test = 31;
var rows = 2;
var text_bsp = "example";
var tab = document.createElement("table");
var line1 = document.createElement("tr");
var line2 = document.createElement("tr");
var cell_date = document.createElement("td");
var cell_event = document.createElement("td");
var cell_day = document.createElement("td");
var cell_place = document.createElement("td");
var ausgabe = document.getElementById('content-container');
ausgabe.appendChild(tab);
for(var i=1;i < 32; i++)
{
tab.appendChild(line1);
for(var j=0;j<3;j++)
{
line1.appendChild(cell_date);
cell_date.createTextNode(text_bsp);
line1.appendChild(cell_event);
cell_event.createTextNode(text_bsp);
}
tab.appendChild(line2);
for(var k=0;j<3;k++){
line2.appendChild(cell_date);
cell_date.createTextNode(text_bsp);
line2.appendChild(cell_place);
cell_place.createTextNode(text_bsp);
}
}
}
I expected a table with 62 lines and 2 rows with the content 'example' in each cell.. But it dont work
If you call appendChild onto a Node that is already part of the DOM, it gets removed from its previous location and moved to the new one. You either have to clone before appending:
line1.appendChild(cell_date.cloneNode(true));
or just create new nodes inside of the loops.
There are are few changes required to achieve what you require. First, you'll need to move you row and cell creation inside the loop - currently you're creating one set of rows outside of the loop, before it begins.
Note also that you can't re-use the same row element, or cell element in the table to generate a table with multiple rows and cells - you need to create new element instances to achieve this.
Also consider using the insertRow(), insertCell() and document.createTextNode() methods as shown below:
function dates() {
var test = 31;
var rows = 2;
var text_bsp = "example";
var tab = document.createElement("table");
var ausgabe = document.getElementById('content-container');
ausgabe.appendChild(tab);
for (var i = 1; i < 32; i++) {
/*
Create line1 row inside of for loop, to produce
a new line for each iteration
*/
var line1 = tab.insertRow(line1);
for (var j = 0; j < 3; j++) {
/*
Create new cell_date and cell_event cells for
the current row we're creating
*/
var cell_date = line1.insertCell();
var cell_event = line1.insertCell();
/*
Create new text nodes for each cell via document
and append these to respective cell elements
*/
cell_date.append(document.createTextNode(text_bsp));
cell_event.append(document.createTextNode(text_bsp));
}
/*
As before, create line2 row inside of for loop
*/
var line2 = tab.insertRow();
for (var k = 0; j < 3; k++) {
var cell_date = line2.insertCell();
var cell_place = line2.insertCell();
cell_date.append(document.createTextNode(text_bsp));
cell_place.append(document.createTextNode(text_bsp));
}
}
}
dates();
<div id="content-container"></div>
I have a table with an id of "mytable", and I have a for loop that builds a 4x4 table, giving each cell an id from 0 to 15 and setting the innerHTML equal to that same number. Once cell is left blank, as this is going to be part of a sliding puzzle game where a user presses a button which scrambles the cells of the table, the solves it by shifting cell positions into that blank space. My issue at the moment is that I can't seem to implement a shuffle function that works. Below is my my code for building a table and shuffling it. See the comments for the error message.
function buildTable(){//need to build it with every cell being named
var tablelocation = document.getElementById('mytable');
var table = document.createElement('table');
table.id="newtable";
for(var i = 0; i<tableSize; i++){
var tableRow = table.insertRow();
for(var j = 0; j<tableSize; j++){
var arrTmp = (tableSize*tableSize-1)-(i*tableSize+j);
var cell = tableRow.insertCell();
cell.id = arrTmp;
if(arrTmp==15){
cell.className = "empty_cell";
else{
cell.className = "cell";
cell.appendChild(document.createTextNode(arrTmp));
}
}
}
tablelocation.appendChild(table);
}
Because the table is built from the bottom right to the top left I have a variable, that handles the values so that once the table is built the numbers appear in the table from 0 to 15 from top left to bottom right.
function shuffleTable(){//need to build it with every cell being named
var table = document.getElementById("newtable");
for (var i = 0; i<tableArray.length; i++) {
var tmp = tableArray[i];//array of shuffled ID values
var tmp2 = objectCellArray[tmp];
objectCellArrayShuffled.push(tmp2);
}
for (var j = 0; j<tableArray.length; j++){
var cell = table.cells[j];//fails here with undefined is not an object error
cell = objectCellArrayShuffled[j];
}
}
I'm calling shuffleTable with a button on my html page.
I've been stuck on this stupid problem for a few days now. I guess it's not complicated but I might need someone's help...
Here is the thing: I start with an empty table in my html page. There is only the head with the name of the columns. Then, I get JSON data thanks to php, and I fill my table by creating a new row and new cells as follows:
for (var j = 0; j < jsonVal.length; j++){
var tr = table.insertRow(-1);
tr.insertCell(-1).innerHTML = "<img src=\"" + jsonVal[j].image + "\">";
tr.insertCell(-1).innerHTML = jsonVal[j].name;
tr.insertCell(-1).innerHTML = jsonVal[j].rating;
};
Now, all I want to do is to update this table according to some parameters (ordered by name or rating, only 5 lines etc...)
To do so, I want to delete all the rows I currently have to put with the new data. BUT I can't find a way to delete them. Here is my deleting code:
var currentTable = document.getElementsByTagName("table")[0];
var rowCount = currentTable.rows.length;
for(var i = 1; i < rowCount; i++){
currentTable.deleteRow(i);
}
I get the following error:
IndexSizeError: Index or size is negative or greater than the allowed amount
Is that the correct way to do it?
PS: sorry for such a long explanation.
My bad, I only needed to change i to 1 in my for loop as follows:
var currentTable = document.getElementsByTagName("table")[0];
var rowCount = currentTable.rows.length;
for(var i = 1; i < rowCount; i++){
currentTable.deleteRow(1);
}
Please read my question complete before answer or marking it duplicate because i am dealing with constraint in my problem.
Hi All Javascript rock stars,
I am creating a html table with javascript. In table i need scroller both vertical and horizontal. I am done with this part. It is working. Now my problem starts. When i am creating millions rows for the table it block my browser. For few thousand record it work fine.
I have done lot of google to improve performance but did not gain any significant performance improvement. Like some has suggested to use row.appendChild(cell); I have also tried to use Workers. But then i found i can not have access of document object in Workers. setTimeout is also not sufficient to solve my problem. Here is my code for creating rows of table.
var arr = JSON.parse(rcvReq.responseText);
var json = arr.abc;
var columns = [];
columns = Object.keys(json[0]);
//Build an array containing Customer records.
var customers = new Array();
customers.push(columns);
for (i = 0; i < json.length; i++) {
var dataVal = [];
for(j = 0; j < columns.length; j++){
var mytempvar = json[i];
dataVal.push(mytempvar[columns[j]+'']);
}
customers.push(dataVal);
}
//Create a HTML Table element.
var table = document.createElement("TABLE");
var table1 = document.createElement("TABLE");
table.border = "1";
//Get the count of columns.
var columnCount = customers[0].length;
//Add the header row.
var row = document.createElement('tr');
row.className = 'fixed-header';
for (var i = 0; i < columnCount; i++) {
var headerCell = document.createElement("TH");
headerCell.innerHTML = customers[0][i];
row.appendChild(headerCell);
}
table1.appendChild(row);
//Add the data rows.
var documentFragment = document.createDocumentFragment();
for (var i = 1; i < customers.length; i++) {
row = document.createElement('tr');
for (var j = 0; j < columnCount; j++) {
var cellVal = customers[i][j];
var cell = document.createElement("TD");
cell.innerHTML = cellVal;
row.appendChild(cell);
}
setTimeout(function(){ }, 1000);
documentFragment.appendChild(row);
}
/* Event of button */
var siblings = e.parentNode.children;
var childOf1stShibling = siblings[0];
table.appendChild(documentFragment);
var div = document.createElement("DIV");
var dvTable = document.getElementById(siblings[1].id +'');
var dvTable1 = document.getElementById(childOf1stShibling.children[0].id + '');
dvTable.innerHTML = "";
dvTable1.innerHTML = "";
dvTable.appendChild(table);
dvTable1.appendChild(table1);
Constraint
No use of jquery. Only i can use javascript, css and html.
No use of third party plugin.
I can not use pagination.
Records are in millions not in thousand.
Please suggest any workaround keeping above constraint in mind.
Thanks so much in advance.
You can check the source of this JavaScript plugin and take the pieces you need. The whole plugin is about 300 rows of code, you can remove some parts if you do not need them. This is a link to their GitHub repo.
On their demo site they append 500k rows and the scroll is smooth.
You can not display that many DOM elements without "blocking" browser.
And there are no "optimization" techniques to handle this, the only option, as mentioned #dandavis would be to listen for scroll events and display subsets on-demand for current scroll position.
As said #Veselin Clusterize.js does exactly that, but it works vertically only. If you need to apply this technique for two directions (horizontally + vertically) - take a look at library called Fattable. Demo
I've been trying to total a list of die rolls (sum of pairs) in a table using javascript to avoid hard-coding 11 rows in my html page and accessing each row seperately later in the js file to add the values.
So I used a loop and document.writeln() to do this in a more compact way but the output doesn't show the table or anything.
document.writeln("<table border=\"1\"><thead><tr><th>Sum of Dice</th><th>Total Times Rolled</th></tr></thead><tbody>");
for (var i=0; i < 11; i++)
{
document.writeln("<tr><td>2</td><td></td></tr>");
}
document.writeln("</tbody></table>");
The rows shouldn't all start with 2, I only used that number as a test and the second tag in the for loop is for the totals that I already have in an array but my issue is with displaying the table.
Try this:
<script>
var code = "";
function write(){
code += "<table border=\"1\"><tr><th>Sum of Dice</th><th> Total Times Rolled</th></tr>";
for (var i = 0; i < 11; i++){
code += "<tr><td>2</td><td></td></tr>";
}
code += "</table>";
document.body.innerHTML = code;
}
</script>
And don`t forget to put this code to html:
<body onload="write()">
Here you have the result:
I think create table by writeln with whole bunch of HTML text string is generally not a good idea. I would recommend create table dom element via Javascript and append it to the wrapper element.
var headerContent = ['Sum of Dice', 'Total Times Rolled'];
var table = document.createElement('table'),
header = table.createTHead(),
row,
cell;
table.border = 1;
// construct header
row = header.insertRow(0);
for (var i = 0, len = headerContent.length; i < len; i++) {
cell = row.insertCell(i);
cell.innerHTML = headerContent[i];
}
// construct table content
for (var i = 0; i < 11; i++) {
row = table.insertRow(i + 1);
for (var j = 0, len = headerContent.length; j < len; j++) {
cell = row.insertCell(j);
cell.innerHTML = '2';
}
}
// add table element to the dom tree
var wrapper = document.getElementById('wrapper');
wrapper.appendChild(table);
See http://jsfiddle.net/LgyuE/