Weird attempt for flicker-free rendering solution

June 23rd, 2007. Tagged: JavaScript

Flicker-free rendering - not allowing the user to see the page loading progress or how the different elements get downloaded and put at their right place. Extra points if the URL in the address bar doesn't change. Why not use AJAX to only change part of the page? Well, don't look at me, but sometimes flicker-free loading of the whole page might be a requirement.

One solution is the frame swapping technique. You have two frames, one has 0% height, the other one 100%. All links target the invisible frame and the new page is loaded there. Once the new page is loaded, it swaps and becomes 100% while the other one that has the old page becomes 0%. And so on. But... frames?

I played around with a different approach. Page A (old page) receives the new URL (of page B) to be loaded. A uses javascript to create a new XML document reading the content of B, then replaces the A nodes with the B nodes.

The solution is nowhere perfect, nor advisable to use, but hey, it's possible.

In for this whole thing to work, all pages should not only be valid XHTML (therefore XML) but also served with the correct content type header:
Content-Type: application/xhtml+xml

Because this whole experiment was done in the Firebug console, I needed to find a site that serves with this header. First one I found was http://www.smackthemouse.com/, so that's why I'm using it as an example. Let's say you're somewhere in the site and lick a Home link. The home URL http://www.smackthemouse.com/ is requested and when it arrives, the current HEAD and the BODY nodes are removed and the HEAD and BODY nodes of the new XML document are added. Finally the document.title is updated. Don't ask why I did it this way exactly, I tried other things like using replaceChild instead of removeChild + appendChild, I tried replacing the HTML node, I even tried innerHTML. Nothing seemed to work in both IE and FF without messing things up, like not applying styles and so on.

So here's what I came up with for Firefox.

var x = document.implementation.createDocument('','',null);
x.load('http://www.smackthemouse.com/');
x.onload = function() {
  var root = document.getElementsByTagName('html')[0];
  root.removeChild(document.getElementsByTagName('head')[0]);
  root.appendChild(x.getElementsByTagName('head')[0]);
  root.removeChild(document.getElementsByTagName('body')[0]);
  root.appendChild(x.getElementsByTagName('body')[0]);
  document.title = x.title;
}

For IE, since it can't createDocument, you need the XMLDOM activeX

var x = new ActiveXObject("Microsoft.XMLDOM");
x.onreadystatechange = function () {
  if (x.readyState == 4) {
    // do the swapping
  } 
};
x.load("http://www.smackthemouse.com/");

So that's all folks, nothing special, just shared headaches and ideas 😀

Another idea - as shown in a previous post, the browsers (except Opera) won't show anything until the last bit of CSS is downloaded. So if you put you big-ass CSS file at the bottom of the page (which is exactly the opposite of what you should be doing when aiming at performance) you might also achieve the desired flicker-free rendering.

Tell your friends about this post on Facebook and Twitter

Sorry, comments disabled and hidden due to excessive spam.

Meanwhile, hit me up on twitter @stoyanstefanov