1

I'm trying to generate a table with a simple 'for' loop, and all rows and cells generate just fine, but they appear empty in Firefox. If you try to log cells' innerText on any stage, the content is there, it seems that it's that breaks everything.

Here's code sample: http://jsfiddle.net/7s8e4w3p/

html

<table id="table">
    <tr>
        <th>This</th>
        <th>Is</th>
        <th>Table</th>
        <th>Header</th>
        <th>in</th>
        <th>JsFiddle</th>
    </tr>
</table>

css

th, td {
    border: 1px solid black;
}

js

for(var i=0; i<=5; i++){
  var tr = document.createElement('tr');
    for(var j=0; j<=5; j++){
        var td = document.createElement('td');
        td.innerText = "test";
        tr.appendChild(td);
    }
  document.getElementById('table').appendChild(tr);
}

Works perfectly well in Chrome, IE, Opera, mobile Safari and even Android browser. What am I missing?

Konstantin
  • 55
  • 10
  • For performance reasons it is often best to generate all the content of your table first and set it all at once so there is only 1 paint/reflow operation vs. several. – scunliffe Dec 07 '14 at 20:26
  • Yes, that's pretty obvious, but the idea was to kind of show the changes over time. – Konstantin Dec 08 '14 at 09:30

2 Answers2

1

The firefox issue is that you're using .innerText, which isn't a standard property.

Use .textContent instead.


To support IE8, I usually create a single variable for my entire application that will reference the proper property name. Like this:

var text = ("textContent" in document.documentElement) ? "textContent" : "innerText";

And then use it like this:

td[text] = "test";

While I don't know that it'll make any difference, you can avoid touching the DOM in the loop by appending to a documentFragment before adding the rows to the table.

// Generic container for holding the rows before they're appended
var frag = document.createDocumentFragment();

for(var i=0; i<=5; i++){
  var tr = document.createElement('tr');
    for(var j=0; j<=5; j++){
        var td = document.createElement('td');
        td.textContent = "test";
        frag.appendChild(td);
    }
}

// Appends all the rows at once
document.getElementById('table').appendChild(frag);
six fingered man
  • 2,460
  • 12
  • 15
  • Thanks man! textContent worked well, and great idea about the td[text] - will keep it in mind for the future. – Konstantin Dec 07 '14 at 21:14
0

Using the "textContent" property is the fix for your code sample, however you can also consider building up a string of HTML content to inject into your table.

var str = '';
for(var i=0; i<=5; i++){
  str += '<tr>';
    for(var j=0; j<=5; j++){
      str += '<td>test</td>';
    }
  str += '</tr>';
}
document.getElementById('table').innerHTML = str;

The main advantage of this is that you build up the entire content first, then in one event insert the content into the table causing only a single paint/reflow event.

Depending on the complexity of your table/content this may perform significantly better than building individual DOM elements and inserting one by one.

See this JSPerf test for a performance comparison: http://jsperf.com/table-generation-options (TL;DR String concatination is faster on desktop browsers, up to 10x faster in Internet Explorer... however on mobile WebKit, DOM methods appear to be faster)

scunliffe
  • 62,582
  • 25
  • 126
  • 161