Tiele Declercq
Tiele Declercq

Reputation: 2150

createElement + createTextNode oneliner?

I'm adding a few thousand rows to a table so i need the speed of native javascript for this one.

Currently I'm using:

nThName = document.createElement("TH");
nThName.appendChild(document.createTextNode(workers[i].name));
nTr.appendChild(nThName);

Is there a way to do this in one line (without losing any performance?) so I don't need the nThName variable?

There are over 50 cells on each row so I would prefer:

nTr.appendChild(document.createElement("TH").appendChild(document.createTextNode(workers[i].name)));

but that don't work.. obviously

Upvotes: 7

Views: 4885

Answers (3)

Tiele Declercq
Tiele Declercq

Reputation: 2150

like David Thomas suggested.. a helper function is clearly the best option:

nTr.appendChild(newElement("TH", workers[i].name));

function newElement(TagName, TextContent, ClassName) {
    var nTag = document.createElement(TagName);
    nTag.className = ClassName;
    nTag.appendChild(document.createTextNode(TextContent));
    return nTag;
}

Changed it with advice by Florian Margaine. Result is super fast. MANY times faster then pure knockout or jquery.

var tplTbody = document.createElement("TBODY");
var tplTr = document.createElement("TR");
var tplTd = document.createElement("TD"); // Every element used has it's 'template'

var nTbody = tplTbody.cloneNode();
for(var i in rows) {
    var nTr = newElement(tplTr.cloneNode(), null, "someclass");
    for(var i in cells) {
        nTr.appendChild(newElement(tplTd.cloneNode(), cell[i].content);
    }
    nTbody.appendChild(nTr);
}
document.getElementById("myTable").appendChild(nTbody);


function newElement(Tag, TextContent, ClassName) {
    if (TextContent !== undefined && TextContent != null)
        Tag.appendChild(document.createTextNode(TextContent));
    if (ClassName !== undefined && ClassName != null) 
        Tag.className = ClassName;
    return Tag;
}

Upvotes: 0

David Thomas
David Thomas

Reputation: 253446

This can be done, as an example:

document.body.appendChild(
    document.createElement('div').appendChild(
        document.createTextNode('hello')
    ).parentNode
);

JS Fiddle representative demo.

I think it's just your approach to chaining that was off; given your specific demo code:

nTr.appendChild(
    document.createElement('th').appendChild(
        document.createTextNode(workers[i].name)
    ).parentNode
);

The white-space here isn't essential, it's simply to more-clearly show what goes where.

Upvotes: 5

Florian Margaine
Florian Margaine

Reputation: 60817

So, you're looking for performance? One-liners don't help with that. Using document fragments and cloning nodes does help, however. But it requires a bit more code.

var table = document.getElementById('t');
var tr = table.querySelector('tr');
var th = document.createElement('th');
var clone;

var df = document.createDocumentFragment();

for (var i = 0; i < 100; i++) {
    // Performance tip: clone a node so that you don't reuse createElement()
    clone = th.cloneNode();
    clone.appendChild(document.createTextNode('hello' + i));

    // Performance tip: append to the document fragment
    df.appendChild(clone);
}

// Performance tip: append only once in the real DOM
tr.appendChild(df);

See jsfiddle demo: http://jsfiddle.net/3KGwh/3/

Document fragments are basically mini-DOM, with limited methods. They're great because they allow you to get great performance, and you can append a single element to the real DOM.

Upvotes: 22

Related Questions