How to update large table with jquery efficient - javascript

I have this code sample which updates cells within the html table.
for (var i = 0; i < o.Rows.length; i++) {
var row = $("tr").filter("[data-id='" + o.Rows[i].Id + "']");
row.find("td:eq(3)").text(o.Rows[i].Status);
row.find("td:eq(4)").text(o.Rows[i].Date);
}
Executing of this sample of code takes a long time if o.Rows.length is 100 000. Is there any more efficient way to do this?

You probably shouldn't have a table with 100,000 rows, but...
You could speed up things a little bit by querying all of them upfront:
var trs = $('tr');
for (var i = 0, l = o.Rows.length; i < l; i++) {
var tr = trs.eq(i);
var o = o.Rows[i];
tr.find('td:first').html(o.Status).next().html(o.Date);
}
Here's a jsperf showing it on 100 lines: http://jsperf.com/table-update/2

Related

double forEach to double for Loop

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.

Delete rows in table built dynamically

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);
}

Creating html table with millions record using javascript blocking browser

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

Hightlight differences between items in table row

I'm trying to add to a HTML table a feature that highlights all those values that, compared to others, are different. Comparison is made row by row.
With great effort I managed to achieve the following JQuery/Javascrit code. I'm pretty sure this is not an efficient/elegant/fast way to do it but it's the only way I work it out.
The HTML table is quite big and complex so it's hard to publish it here.
The issue I'm encountering is that the script works fine out of a loop, but it hangs if I put it inside a FOR - LOOP and I don't understand why.
var numRows = $('.ctable tbody tr').length, numCols = $('.ctable tbody tr:first th').length, v, undefined;
var values = new Array(numRows);
var noDuplicates = new Array(numCols);
var result = new Array(numCols);
for (i = 1; i = numRows; i++) {
// Get a row and copy into an array the values of each VISIBLE cell
$(".ctable tbody tr:eq(" + i + ") td.values:visible").each(function(){
v = $(this).text();
values.push(v.trim());
});
// Remove from the array the 'undefined' values
values = values.filter(function(item){
return item !== undefined;
});
// Push into new array duplicate values
noDuplicates = return_duplicates(values);
// Compare the two arrays and get the differences (uses underscore.js)
result = _.difference(values, noDuplicates);
// This is a 'highlight' plugin and you may pass to it an array
$(".ctable tbody tr:eq(" + i + ") td.values:visible").highlight(values);
}
function return_duplicates(arr) {
var len=arr.length, out=[], counts={};
for (var i=0;i<len;i++) {
var item = arr[i];
counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
}
for (var item in counts) {
if(counts[item] > 1)
out.push(item);
}
return out;
}
Try
for (i = 1; i < numRows; i++) {
instead of
for (i = 1; i = numRows; i++) {

Javascript html table not showing

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/

Categories

Resources