views:

104

answers:

4

I've currently run into a performance problem when updating properties on lots of dom elements at once. It seems that each time I change a property the dom element gets re-rendered. Is there anyway I can delay the rendering of the elements until all of my updates have taken place? It seems to be a lot slower in FF 3 & 3.5 than IE 7 & 8 which goes against what i expected.

An example of what i'm doing is below.

var t;

for (var i = 0; i < tiles.length; i++) {
    t = tiles[i];
    t.width = '100';
    t.height = '100';
}

The issue is that the number of items in "tiles" can be up to 100 dom elements. Which is where the performance issues really show through.

A: 

Declare display:none for each tile before you make changes and display:block when all changes are done.

Crimson
+2  A: 

Agree with @Crimson but I think that it will be better to hide the parent of all the elements that you're updating and if they don't have an exclusive parent, try to create one.

In that way only two reflows will occur, one when you hide the tile container, and other when you finish the element manipulation and you show it again.

CMS
Awesome i'll give that a go.
Alex
If the concern is about reflows, why not use visibility: hidden. This will keep the elements where they are.
David Andres
visibility:hidden doesn't seem to have the same performance.
Alex
It works beautifully, Except! ff2 shows a brief white flash :( Is there anyway to prevent that?
Alex
@David, I don't think visibility:hidden; would work as changes can potentially have an affect on the amount of space taken up by the element in question.
J-P
A: 

To avoid the flash you could replace the parent with a clone of itself and then work on the original parent outside of the document. Then, when you're done, you could replace the clone with the original:

var parent = /* define parent here */;
var clone = parent.cloneNode(true);

parent.parentNode.replaceChild(clone, parent);

/* Do stuff with parent and its childNodes... */

clone.parentNode.replaceChild(parent, clone);
J-P
A: 

It seems to be a lot slower in FF 3 & 3.5 than IE 7 & 8 which goes against what i expected.

Currently FF recalculates the layout straight away on a property change. IE waits until either it has to redraw the page, or you access a property like offsetWidth that needs to know the new layout. This didn't always used to work correctly.

CMS's approach is good. If all your tiles are the same size as in the example, there's an even quicker way (which also works if the tiles don't have a common parent). Just give them all a class and switch them all at once using CSS:

body.tiles100 .tile { width: 100px; height: 100px; }

document.body.className= 'tiles100';

If you don't know a predefined selection of possible sizes in advance, you'd have to write the stylesheet rule dynamically, through the document.styleSheets list. This is a bit of a pain, though, because the scripting interface in IE doesn't quite match the DOM standard used by other browsers. Again.

bobince