views:

42

answers:

4

Client side javascript code create some elements (about 50-100) in cycle:

for (var i = 0; i < list.length; i++) {
   var obj = document.createElement("DIV");
   obj.innerHTML = "<span class=\"itemId\">" + list[i].Id 
                   + "</span><!-- some more simple code --> ";

   mainObj.appendChild(obj);
}

There is some problem with browser rendering, for example IE just freeze until he finished the cycle and then shows all elements in one time. Is there a way to show each created element separately and immediately after "appendChild()"?l

+1  A: 

insert a delay between adding successive entries, with setTimeout().

function insertEntry(list, ix) {
    if (ix == null) {
        ix = 0;
    }
    else if (ix < list.length) {
        var elt= document.createElement("DIV");
        var attr = document.createAttribute('id');
        attr.value = 'item'+ix;
        elt.setAttributeNode(attr);
        elt.innerHTML = "<span class='itemCls'>" + list[ix].Id + ':&nbsp;' + list[ix].Name +
            "</span><!-- some more simple code -->\n";
        mainObj.appendChild(elt);
        ix++;
    }
    if (ix < list.length) {
        setTimeout(function(){insertEntry(list, ix);}, 20);
    }
}

Kick it off with:

    insertEntry(myList);

where myList is like this:

var myList = [
    { Id : '1938377', Name : 'Sven'},
    { Id : '1398737', Name : 'Walt'},
    { Id : '9137387', Name : 'Edie'}
    ...
 };

demo: http://jsbin.com/ehogo/4

Cheeso
+2  A: 

This is due to the single threaded nature of browsers. Rendering will not begin until the thread becomes idle. In this case, it's when your loop has completed and the function exits. The only way around this is to (sort of) simulate multiple threads using timers, like so:

var timer,
    i = 0,
    max = list.length;

timer = window.setInterval(function ()
{
    if (i < max)
    {
        var obj = document.createElement("DIV");  
        obj.innerHTML = "<span class=\"itemId\">" + list[i].Id   
                + "</span><!-- some more simple code --> ";  

        mainObj.appendChild(obj);
        i++;
    }
    else
        window.clearInterval(timer);
}, 1);

The obvious drawback is that this will take your loop longer to complete because it's fitting the rendering inbetween each iteration.

Andy E
Ops.. you beat me to it :-)
Marcos Placona
+1 for explaining *why* to setTimeout.
Boldewyn
A: 

I wold do it like this using jQuery instead:

<!DOCTYPE html>
<html>
<head>
    <script src="http://code.jquery.com/jquery-latest.js"&gt;&lt;/script&gt;
    <script>
        $(document).ready(function() {
            timer = window.setInterval(function ()
            {
                for (var i = 0; i < 100; i++) {
                    $('#container').append('<div>testing</div><br />');
                }
            },10);
        });
    </script>
</head>
<body>
<div id="container"></div>

</body>
</html>

jQuery does it so quickly, you won't even need to bother about showing as they are created, but you can make it smoother by adding a timer as the example shows.

Marcos Placona
jQuery can't make for loops and DOM creation any quicker. In fact, jQuery's regular expressions for converting HTML to DOM nodes would make it slower.
Andy E
A: 

Is there a specific reason you want the DOM to be updated after every cycle? It would be alot faster if you create all the elements in one javascript element, and add this one element to the DOM when the cycle is finished.

var holder = document.createElement("DIV");
for (var i = 0; i < list.Length; i++) {
   var obj = document.createElement("DIV");
   obj.innerHTML = "<span class=\"itemId\">" + list[i].Id 
                   + "</span><!-- some more simple code --> ";

   holder.appendChild(obj);
}
mainObj.appendChild(holder);
Jasper De Bruijn
I would like to avoid browser freeze. If user will see that the rows adding to the page he will see the progress (in IE even progress showing image freeze).
Sirius Lampochkin