# Can I adjust this code which displays a table to run faster?

this.displayData = function () {
var i;
var $thead =$(thead);
var $tbody =$(tbody);
var numberOfFields = columnDataFields.length;
var numberOfRows = data.length;

// Variables to keep track of even and odd rows.
var evenRowClass = 'EvenBar';
var oddRowClass = 'OddBar';
var t = false;

$tbody.html(''); // Find the widths of the column headers and apply the same widths here. // However, only do this if the colWidths are thus far undefined. if (!colWidths) { colWidths = []; var headers =$thead.find('td');
var colWdith;
for (i = 0; i < headers.length; i++) {
colwidth = $(headers[i]).outerWidth(); colWidths.push(colwidth);$(headers[i]).css('width', colwidth); // This statement is necessary for cross-browser compatibility. (The problem is with discrepencies in "computed" CSS.)
}
}
for (x in data) {
var entry = data[x];
var row = ['<tr class="'];
row.push(t ? evenRowClass : oddRowClass);
row.push('">');
for (i = 0; i < numberOfFields; i++) {
row.push('<td style="width:');
row.push(colWidths[i]);
row.push(';">');
row.push(entry[columnDataFields[i]]);
row.push('</td>');
}
row.push('</tr>');

$tbody.append(row.join('')); t = !t; } // If a callback function was set, invoke it. if (typeof displayCallback === 'function') displayCallback(); } // end displayData  • Your first line on your code block is not indented. I tried to fix it, but it says it is not a valid edit. lol – epascarello May 23 '12 at 17:47 ## 2 Answers You don't need to redraw the entire table. Try just doing DOM manipulation to reorder the TRs. I see that you also want to stripe the rows, but you can still do it with DOM manipulation. You should be able to take it from there. I created a simple example with almost 1000 rows and it runs almost instantaneously. There's some jQuery just so I don't have to worry about cross-browser issues. If you don't use jQuery, most libraries have the functionality I used,or you can just implement $.text on your own http://jsfiddle.net/unffs/2

var table = document.getElementById('tbl');
// Can't call sort on an HTML collection, so copy the contents to an array
var rows = Array.prototype.slice.call(table.rows);
rows.sort(function(a, b) {
var aVal = $(a).text(), bVal =$(b).text();
return aVal > bVal ? 1 : (bVal > aVal ? -1 : 0);
});
var tbody = document.getElementById('tbody');
for (var i=0; i < rows.length; i++) {
tbody.appendChild(rows[i]);
}


That code works for a table like the following

<table id='tbl'>
<tbody id='tbody'>
<tr><td>D</td></tr>
<tr><td>A</td></tr>
<tr><td>C</td></tr>
<tr><td>E</td></tr>
<tr><td>F</td></tr>
<tr><td>B</td></tr>
<tr><td>D</td></tr>
</tbody>
</table>


Using data to sort instead of HTML

If you have some underlying data for the table, it will be even faster since you won't need to read the DOM (except for an id attribute)

var data  = [
{id: 1, value: 'C'},
{id: 2, value: 'B'},
{id: 3, value: 'D'},
{id: 4, value: 'A'}
];


<table id='tbl'>
<tbody id='tbody'>
<tr id='row-1'><td>C</td></tr>
<tr id='row-2'><td>B</td></tr>
<tr id='row-3'><td>D</td></tr>
<tr id='row-4'><td>A</td></tr>
</tbody>
</table>


Here's the code to sort the table

var table = document.getElementById('tbl');
// Can't call sort on an HTML collection, so copy the contents to an array
data.sort(function(a, b) {
return a.value > b.value ? 1 : (b.value > a.value ? -1 : 0);
});
var tbody = document.getElementById('tbody');
for (var i=0; i < data.length; i++) {
tbody.appendChild(document.getElementById('row-' + data[i].id));
}

• So, what you're saying is that you call the sort function on the collection of rows itself, instead of sorting the underlying data and then redisplaying all the rows? – Vivian River May 23 '12 at 18:09
• @RiceFlourCookies Your explanation is a simplification of what I wrote in the code but is not 100% accurate, so let me reiterate. You can sort just the rows (by copying to a new array as in my example), then re-inserting them in the sort order. You can use the underlying data in the comparison instead of the HTML contents, just associate each HTML row with your data. See my updated example – Juan Mendes May 23 '12 at 20:53

Updating tables are one of the hardest things to do since they take a long time to render. That is why people say do not use them for layouts. 1000's of rows are also bad, it would be a lot better to paginate it and only show a smaller subset.

The problem you have is you are adding rows one by one. That is bad. You need to bulk add. Multiple updates to the DOM means the table has to keep recalculating which results in slow redraws. Basic idea of doing a bulk add:

    var rows = [];
for (x in data) {
var entry = data[x];
rows.push('<tr class="');
rows.push(t ? evenRowClass : oddRowClass);
rows.push('">');
for (i = 0; i < numberOfFields; i++) {
rows.push('<td style="width:');
rows.push(colWidths[i]);
rows.push(';">');
rows.push(entry[columnDataFields[i]]);
rows.push('</td>');
}
rows.push('</tr>');
t = !t;
}
$tbody.append(rows.join('')); // add it once  Another thing you can do is append it to a tbody and than use replaceWith. $tbody.replaceWith("<tbody>" + rows.join('') + "</tbody>);


other option is remove and append

\$tbody.remove();
MY_TABLE_VARIAVLE.append("<tbody>" + rows.join('') + "</tbody>);

• Can you please clarify exactly what you mean by "the table has to keep recalculating"? – Vivian River May 23 '12 at 18:10
• @epascarello The OP was inserting the HTML for the table at once, so there's no recalculating. It's a one time calculation accounting for all the rows. – Juan Mendes May 23 '12 at 20:54