Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Effectively Build Table From JSON and Add It to DOM

I have a JSON array coming in from the server with an array of 200 objects each containing another 10 objects that I want to display in a table format. At first I was creating a <tr> for each iteration and using jQuery to append a <td> built from the array values to the <tr>. This was taking around 30 seconds in Chrome and 19 seconds in IE 8. This was taking too long so I tried switching to the Array.join() method, where I would store each string that would make up the entire table in an array, and at the end do $('#myTable').append(textToAppend). This actually performed worse than my first version by around 5 seconds.

I would like to get this to around 10 seconds. Do I have any chance at that? If not, I'm just gonna add one row at a time, but I'd rather not do that.

for(allIndex = 0; allIndex < entries.alumnus.length; allIndex++){

  var entry = '<tr id="entry' + allIndex + '" class="entry"></tr>';
  $('#content_table').append(entry);

  $('#entry' + allIndex).append(($.trim(entries.alumnus[allIndex].title) != '' ?
        '<td id="title' + allIndex + '" class="cell"><span class="content">' +
         entries.alumnus[allIndex].title + '</span></td>' : '<td width="5%">' + 
         filler + '</td>'));    
  .
  .
  .
  .//REST OF ELEMENTS
  .
  .
  .
}   

UPDATE: I must have messed something up yesterday, because I went back to trying appending elements out of the DOM and then attaching them later, without using jQuery and I've gotten my time down to 85 ms in Chrome and 450 ms in IE7!!! You guys are awesome!!! I gave user1 the answer because that one was more comprehensive, and using fragments didn't really change my times much in Chrome and added around 20ms in IE7. But I still appreciate @Emre Erkan's answer, and will utilize more often :)

like image 494
Eliezer Avatar asked Jan 04 '12 22:01

Eliezer


1 Answers

The fastest will look something like this:

var oldTable = document.getElementById('example'),
    newTable = oldTable.cloneNode(true);
for(var i = 0; i < json_example.length; i++){
    var tr = document.createElement('tr');
    for(var j = 0; j < json_example[i].length; j++){
        var td = document.createElement('td');
        td.appendChild(document.createTextNode(json_example[i][j]));
        tr.appendChild(td);
    }
    newTable.appendChild(tr);
}

oldTable.parentNode.replaceChild(newTable, oldTable);

And should run in milliseconds. Here is an example: http://jsfiddle.net/Paulpro/YhQEC/ It creates 200 table rows each containing 10 td's.

You want to append using elements, not strings, but you don't want to append anything to the DOM until you're done creating the entire structure (to avoid reflow in your loop). So you can clone the original table and append to the clone, then insert the clone after your loop completes.

You will also gain a fair bit of speed by avoiding jQuery and interacting with the DOM directly.

Your code may look like:

var oldTable = document.getElementById('content_table'),
    newTable = oldTable.cloneNode(true),
    tr, td;
for(var i = 0; i < entries.alumnus.length.length; i++){
    tr = document.createElement('tr');
    tr.id = 'entry' + i;
    tr.className = 'entry';

    if(entries.alumnus[i].title){
        td = document.createElement('td');
        td.id = 'title' + i;
        td.className = 'cell';
        var span = document.createElement('span');
        span.className = 'content';
        span.appendChild(document.createTextNode(entries.alumnus[i].title);
        td.appendChild(span);
        tr.appendChild(td);
        tr.appendChild(createFiller(filler));
    }

    // REST OF ELEMENTS

    newTable.appendChild(tr);

}

oldTable.parentNode.replaceChild(newTable, oldTable);

function createFiller(filler){
    var td = document.createElement('td');
    td.style.width = '5%';
    td.appendChild(document.createTextNode(filler);
    return td;
}
like image 199
Paul Avatar answered Sep 16 '22 21:09

Paul