tags:

views:

39

answers:

5

I've got a loop where I insert about 500 <div>s into the DOM via document.getElementById(target).appendChild(docFragmentDiv), and each <div> has probably 20 or 30 descendants. I can insert up to about 100 just fine, but the page temporarily freezes while the DOM is updated if there's something like 200+ inserts.

How can I avoid this choke? Right now I have an interval set up to insert 50 per interval, with 25 ms between intervals. Is there a better way to do this?

A: 

innerHtml() is almost always faster than appendChild().

Have a look at QuirksMode's benchmarking for real numbers.

Edit: Is there any reason why you're adding them in intervals rather than all at once? I think SLaks is right about doing it all at once.

Skilldrick
I don't think you are correct. I've tried innerHTML += instead of appendChild() and the page freezes much sooner.
JamesBrownIsDead
Don't do `innerHTML +=`. Assemble a string array, call `join`, then set `innerHTML` only once.
SLaks
@Slaks: This is correct. Adding innerHTML over and over is simply causing the page to rerender every time, same as it would be iteratively adding elements through DOM methods. Whatever you do, draw the page only once.
Robusto
A: 

I'm not sure if this would be any faster, but it would be the first thing I tried:

Instead of adding them all to the page, add them all to a container that you haven't yet added to the page, and then add that container to the page.

If that improves performance, then you can modify it to suit your needs.

Gabriel McAdams
+2  A: 

You should use innerHTML, and you should use it only once.

For optimal efficiency, you should assemble pieces of HTML in an array of strings using a loop, then write document.getElementById(target).innerHTML = htmlPieces.join()

SLaks
When I have simple stuff to do, I use the DOM methods for creating/adding elements. When I have to add huge numbers of elements, creating them as strings and adding thru innerHTML is orders of magnitude faster.
Robusto
A: 

Be careful that you aren't using appendChild to the actual document until the last instant. In other words, if you're doing:

var div1 = document.createElement("div");
document.body.appendChild(div1);

for (var i=0; i<500; i++) {
  var div = document.createElement("div");
  div1.appendChild(div);
}

Then you are redrawing the entire page every time you iterate in that loop.

Better, if you're using DOM methods, to reverse this:

var div1 = document.createElement("div");

for (var i=0; i<500; i++) {
  var div = document.createElement("div");
  div1.appendChild(div);
}

document.body.appendChild(div1);

Now you are drawing your divs to an offscreen buffer, and only making the page redraw once.

Robusto
A: 

Using innerHTML like SLaks suggests will work, but it's probably better practice to create a document fragment, append all of your div nodes to that, then append the document fragment to the main document.

var docFrag = document.createDocumentFragment();

for (var i=0; i<500; i++) {
    docFrag.appendChild(document.createElement("div"));
}

document.getElementById(target).appendChild(docFrag);

nickjsify