Efficient Javascript for DOM modifications
Asked Answered
E

4

5

Say, I've got an HTML file that I want to process using Javascript. For example:

  • Add some DOM elements, like span or div wrappers.
  • Change the document styling a bit, like base font size, line-height, etc.
  • Use a hyphentor to add ­ entities.

What would be the most efficient way to do this, i.e. I'd like to do it with a minimum amount of reflows.

The ideal case would be having the JS-code run before even the first layout. Is this possible? I know, it's generally a bad idea to execute expensive scripts before the page has been displayed for this would make the page look blank for some time and it's a really bad experience. However, I'm going to need this to work offline and this would not be an issue for my project.

Or, is there's a way to do all the dom modifications in one bunch, i.e. a reflow to be triggered after all the alterations have finished?

Edwyna answered 7/7, 2012 at 10:34 Comment(0)
F
6

There are several ways. The primary goal with all of them is that you end up causing a single - or at least as few as possible - reflows/repaints.

Off-DOM element

You can work with elements without appending to the DOM, and then just append everything together once everything's set up.

The only issue with this is if your code needs to reference offset dimensions, since elements not yet in the DOM do not have any.

var container = document.createElement('section'); //not in the DOM yet
//do some extensive work here to prepare the doc
document.body.appendChild(container); //now we go to the DOM, causing a single re-paint

Doc fragment

A more formalised, and possible improved, variation on this theme would be document fragments, which bring a performance benefit (apparently). They're effectively a second, separate DOM that has no display.

String

Probably the quickest of all of these would be to build up your document as a string. The obvious implication is you can't use DOM methods on it, but if you're happy string-handling and REGEX'ing (not ideal on HTML, of course), could be worth considering.

Finally, if speed is of the essence and you have a LOT of computation or string-handling to do, you might want to harness web workers. These can't talk to the DOM directly, but you can outsource tasks to them and, crucially, they work asynchronously on a separate thread.

Folkestone answered 7/7, 2012 at 10:46 Comment(0)
A
3

Remove the documentElement from the document, modify it and add it back to the document.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>...</title>           
    </head>
    <body>
        <script type='text/javascript'>
var docElem = document.documentElement,
    parentNode = docElem.parentNode,
    nextSibling = docElem.nextSibling;
parentNode.removeChild(docElem); // reflow
// ...
docElem.lastChild.appendChild(docElem.ownerDocument.createElement('hr'));
// ...
parentNode.insertBefore(docElem, nextSibling); // reflow
        </script>
    </body>
</html>

This triggers two reflows and zero to two extra repaints.

jsFiddle

Academic answered 7/7, 2012 at 11:32 Comment(0)
Z
0

I believe it's up to browser to decide then to reflow content. And they try not to do it until script execution is finished. What important to note here that when you, for example, append div to the document body it causes DOM recalculations. And for that you can use documentFragment to append elements and then fragment itself to the body. Though if in your case it happens that you need to append 1 element to different containers it won't help much.

Additional read on documentFragment: http://ejohn.org/blog/dom-documentfragments/

Zenas answered 7/7, 2012 at 10:42 Comment(0)
T
-1

I think u cannot work on style or DOM elements before page loaded. First its loaded then you start tweaking page. I would load page hiddenly tweak it and show. Ways to hide:

  1. everything load outside screen X/Y coordinates, then u put it to 0,0
  2. DIV which contents page data have style : Display:None or visibility:hidden http://www.w3schools.com/css/css_display_visibility.asp check here for details.
  3. It can be u load page inside 1 pixel iframe, u as parent page owner have control over child page. After finishing ur tweaks resize iframe, hide its frame.
  4. Use Z index and put fullsize non transparent DIV black or white which hides everything under. Remove it when u ready

Choose what better suits your style.

Tangelatangelo answered 7/7, 2012 at 10:46 Comment(1)
Even if this is an really old answer I still recommend to NOT link to w3schools.com because of this: w3fools.com :)Koerlin

© 2022 - 2024 — McMap. All rights reserved.