2

I have a JavaScript Object with some information in it.

I have 2 options I can think of to create the HTML from this object. I was wondering which one is the correct way of doing things of is this just all preference?

1) Loop through this array with JavaScript and create the HTML with Jquery?

2) Ajax post/get the object to PHP and loop through this object(php array) and create the HMTL that way? Then return a json encoded object back with the HMTL in it and append it to a div?

What I currently Do to build

    var OutterDiv = $(document.createElement('div'));

    for loop{
        OutterDiv.append("<span>SOME INFO</span>");


        var InnerDiv = $(document.createElement('div'));
        for loop{
            InnerDiv.append("<span>SOME INFO</span>");
            InnerDiv.append("<span>SOME INFO</span>");
        }

        OutterDiv.append(InnerDiv);
    }


    $("#content").append(OutterDiv);
Robert
  • 742
  • 1
  • 7
  • 14
  • It doesn't really matter how you get the html as long as you append it efficiently. For example, appending an entire document fragment or html string is more efficient than appending 1 element at a time in a for loop. – Kevin B May 18 '12 at 15:37
  • @Kevin B - So question I have is appending in that loop would be considered slow? But I dont really append to DOM until I build the DIV... – Robert May 18 '12 at 15:40
  • what you are doing is fine because you are appending to a document fragment, not the document. – Kevin B May 18 '12 at 15:49

3 Answers3

2

Why don't you loop through the object and create an HTML string from JavaScript? Then insert that string wherever you need it? I believe this is the fastest way you can accomplish what you want do do. The main idea is that concatenating strings is faster than inserting DOM elements, and perhaps faster than the latency caused by an Http request.

** Edit **

Apparantly, IE is slower at string concatenation (big surprise) and using an array is better. Example :

var html = [];
for (...) {
   html.push( <some html content from your object here> );
}
$(selector).html(html.join(''));

// find the elements you need to handle and perform bindings here
// ex: $('#someelment').click(...);

This is probably as fast as you can get.

** Update **

While performing the task of building HTML with JavaScript is still generally faster, after some testing, it seems that concatenating strings, or building arrays are not faster than creating text nodes. The test can be viewed and forked on jsfiddle.net or here it is for archiving pruposes :

function runTest(testFn, duration) {

    var endTime = +new Date() + duration;
    var runs = 0;
    var charCount = 0;

    while (+new Date() < endTime) {
        charCount += testFn();
        ++runs;
    }        
    teardown();

    //console.log(testFn.title, 'ran', runs, 'times.');
    $('#log').append($('<div></div>').text(testFn.title + ' ran ' + runs + ' times (' + (charCount/1000) + ' cps).'));
}

///

function teardown() {
    while (targetDiv.firstChild) {
        targetDiv.removeChild(targetDiv.firstChild);
    }
}

///

var testData;
var sample, sampleData;
function generateTestData() {
    testData = {};
    for (var i=0; i < (Math.random() * (sample[1]-sample[0])) + sample[0]; i++) {
        testData['item'+i] = randomString();
    }
}


function randomString()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789";

    for( var i=0; i < (Math.random() * (sampleData[1]-sampleData[0])) + sampleData[0]; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

function shuffle(arr) {
    var len = arr.length;
    var i = len;
    while (i--) {
        var p = parseInt(Math.random()*len);
        var t = arr[i];
        arr[i] = arr[p];
        arr[p] = t;
    }
    return arr;
};

///

var $targetDiv = $('#targetDiv');
var targetDiv = document.getElementById('targetDiv');

///

function jq() {

    var html = [];
    var count = 0;

    for (var key in testData) {
        count += testData[key].length;
        html.push('<div>' + testData[key] + '</div>');
    }

    $targetDiv.html(html.join(''));

    return count;
}

function inner() {

    var html = [];
    var count = 0;

    for (var key in testData) {
        count += testData[key].length;
        html.push('<div>' + testData[key] + '</div>');
    }

    targetDiv.innerHTML = html.join('');

    return count;
}


function dom() {

    var root = document.createElement('div');
    var node;
    var count = 0;

    for (var key in testData) {
        count += testData[key].length;
        node = document.createElement('div');
        node.appendChild(document.createTextNode(testData[key]));
        root.appendChild(node);
    }
    targetDiv.appendChild(root);

    return count;            
}

///

jq.title = 'jQuery .html';
inner.title = 'innerHTML';
dom.title = 'DOM';

///

sample = [10, 100];
sampleData = [100, 1000];
generateTestData();

var duration = 1000;
var testFn = shuffle([jq, inner, dom]);

$.each(testFn, function(k, fn) {
    setTimeout(function() { runTest(fn, duration); }, 0);
});
​

Overall, while each method is more efficient under some conditions (lots of or few data, long or short strings, etc.), the DOM method seems generally faster in all cases.

So, there you have it. Thanks to GGG for the initial test case.

Community
  • 1
  • 1
Yanick Rochon
  • 45,203
  • 21
  • 112
  • 182
  • Maybe I'm reading this wrong, but I don't see how string concatenation followed by something like innerHTML would be faster than skipping the string concatenation step and just inserting DOM elements... Do you have some kind of performance test to back up this claim, or am I just misreading you? – Dagg Nabbit May 18 '12 at 15:31
  • I was going to ask the same thing? Ill add some sample code of whaT I am currently doing. I don't insert it until after I build – Robert May 18 '12 at 15:33
  • each time you insert an element into the DOM, the document gets reparsed and re-indexed. If you use `innerHTML` once, this process is done only once. – Yanick Rochon May 18 '12 at 15:33
  • @YanickRochon, that's why you build the entire subtree before inserting it into the document. – Dagg Nabbit May 18 '12 at 15:34
  • 1
    unless you need to handle events to a specific created element, there is no need to create jQuery-object-wrapped elements with each and every created elements. – Yanick Rochon May 18 '12 at 15:37
  • @GGG: youre still reparsing the Fragment then arent you? – prodigitalson May 18 '12 at 15:37
  • @prodigitalson not really, there's no "parsing" going on at all. No DocumentFragments needed either, really. Just do something like `var root = document.createElement('div')` and then append children to root, and when it's all ready, insert it into the document. OTOH if you use innerHTML, there is string concatenation, and parsing, and finally building the DOM, so I can't imagine that's any faster... – Dagg Nabbit May 18 '12 at 15:39
  • 1
    [This](http://stackoverflow.com/q/117665/901048) [has](http://stackoverflow.com/q/2202269/901048) [been](http://stackoverflow.com/q/7307087/901048) [discussed](http://stackoverflow.com/q/2319472/901048) [extensively](http://ejohn.org/blog/dom-documentfragments/) [elsewhere](http://www.quirksmode.org/dom/innerhtml.html). – Blazemonger May 18 '12 at 15:47
  • @Blazemonger this test doesn't take into account the overhead of string concatenation to get the initial markup. Also, these browsers are ancient. – Dagg Nabbit May 18 '12 at 16:02
  • @GGG Well, that's where the reading comes in. You can run the "test now" links on the page in whatever browsers you like. I'll leave the links up there so you can review them when you're not so busy. – Blazemonger May 18 '12 at 16:03
  • The point is not made. The PPK test is a troll, it doesn't deal with the *realities* of string concatenation with real data, it simply appends the same strings over and over, which is easily optimized. All of the jQuery links are basically irrelevant. Some of the links infer that DocumentFragment is faster, some infer innerHTML is faster, etc. This is anything but conclusive. Anyway, @YanickRochon, I asked *you* if *you* had any evidence to back this up. Why not simply provide a good source to back up your claim? (I am almost certain I can flip this PPK test on its head in a real-world test.) – Dagg Nabbit May 18 '12 at 16:21
  • @GGG I modified my answer, read the link to another similar question on SO. – Yanick Rochon May 18 '12 at 16:29
  • @YanickRochon jsperf.com is down right now, but I put together a fiddle which seems to indicate normal DOM manipulation is significantly faster than innerHTML. Can you find any mistake or bias in this test? I tried to make it as unbiased as possible, and it's based on your latest update. http://jsfiddle.net/FTj7Q/1/ -- It's not my intent to derail your thread, but I think it's important to explore claims like this for one's self, rather than just relying on third parties. I am genuinely curious if you can get innerHTML to run faster somehow. – Dagg Nabbit May 18 '12 at 17:42
  • I stand corrected. This is actually shocking to me as strings are supposed to be a primitive type in JavaScript and object creation should always be slower than primitive operations... This is interesting. – Yanick Rochon May 18 '12 at 18:44
  • @YanickRochon one interesting thing is that the speed difference decreases as the size of the subtree increases... for example if you enclose the `for` loops in `while` loops that count down from, say, 1000, and extend the timeout a bit, you'll notice the numbers getting closer together. So with *huge* datasets it might be possible that innerHTML is faster, but I couldn't actually get that far without hanging the browser... – Dagg Nabbit May 18 '12 at 19:07
  • yes, I thought of making the tests asynchronous (using `setTimeout` to "resume" the test, etc.) but I didn't go that far. Usually, people don't need nor want to add +30k items of data :) – Yanick Rochon May 18 '12 at 19:51
  • @YanickRochon +1 from me, it's the least I can do at this point ;) – Dagg Nabbit May 19 '12 at 03:35
1

Do it in javascript. If you already have the data in javascript, taking an extra trip to the server to have PHP do it (letting javascript broker that connection) is wasteful. If it was an intensive calculation, it might make sense to let PHP do it because of speed, but otherwise, seems like a waste.

Brian Warshaw
  • 21,296
  • 8
  • 50
  • 70
0

You could use JSON.stringify(array) to encode your array in JavaScript, and then use $array=json_decode($_POST['jsondata']); in your PHP script to retrieve it.

jugnu
  • 141
  • 6
  • in this way you should go for jqeury .append() or .html() or you can simply create html string in javascript and pass it on to ur html page – jugnu May 18 '12 at 15:50