Implementing a Web Application Preloading Overlay

By on October 6, 2008 10:01 am

A common issue encountered when developing web applications with the Dojo Toolkit is a startup lag caused by the dynamic loading of modules and resources, further aggravated by a flash of unstyled content before the template system kicks in and sets up your widgets. This is especially true when using numerous Dijit components, and even more apparent when not using a custom build (such as loading your files from the Google or the AOL CDN). While it is typically recommended to use a custom build, it isn’t always practical, or even necessary. Perceived speed is speed, and we should do something about it.

Dojo is a very flexible toolkit, and can bend and otherwise be manipulated to handle any use case. Personally, I am a fan of the progressive use case: where JavaScript is used to enhance an otherwise perfectly working collection of clean markup and good styles. Sometimes though, especially in the case of intranet applications or “admin panel” type web interfaces, you will find yourself using many layout widgets and form components. Delivering content quickly in this case is essential, and hiding any ugliness resulting from template substitution is a vital aspect to delivering the best possible user experience. Today, I’m going to go over a common technique to provide at least the perception of perfectly designed full-page layout applications.

We’ll start with a sample application, loading Dojo and several Dijit components from the AOL CDN tree:




	Beefy Layout Page

	 
	
	

	
	
	



	

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus, mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. Nam tempus ornare lorem. Nullam feugiat.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus, mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. Nam tempus ornare lorem. Nullam feugiat.

You can see this example in action now.

The total size of CSS, JavaScript and HTML is 645KB, spread across 91 requests, taking a total of 2.13 seconds to load and parse when loaded from the local file system. This is less than ideal, and we’ve not even started added complex content! (To be fair, this code includes all comments inline, and no effort has been made yet to optimize this code.) You can see the various lorem paragraphs jump into place, much to the dismay of your designers and users alike. The build system will reduce this impact significantly, but we’re still just developing here, and keeping all the code modular is in our best interest.

Updating all Dojo URLs to point to the AOL CDN, we are able to reduce the page overhead to 104KB, taking a total of 2.12 seconds. In the next article we’ll convert this to a local tree again, and illustrate how a custom build can optimize this even further.

You’ll notice we’re calling dojo.parser.parse() from within a dojo.addOnLoad() function. Had we set djConfig.parseOnLoad = true, any registered addOnLoad functions wouldn’t execute until after parsing takes place. In most cases, this is convenient. In this case, however, we want more granular control over page-load behavior.

The technique we’ll be using to hide the rendering process is simple, and mostly uses plain CSS selectors and design, and minimal amounts of JavaScript to achieve the desired results. We start by adding a new node with position:absolute, taking it out of the layout flow, giving it a high z-index, and a centered background-image of a spinning loader. We’ll then overlay this node across the entire viewport, and do all of our parsing in the background. Add a DIV element with an id of “preloader” in the page (as close to the top of the markup as possible is best, but will work anywhere), and some simple rules:


If all you see is a spinning icon, we’ve succeeded. Granted, we can’t interact with our page at all now, but we didn’t see any unstyled content. The next step would obviously be to show the content immediately after dojo.parser has run. This is where it is important to have onLoad parsing turned off (via djConfig.parseOnLoad = false) because, as mentioned earlier, addOnLoad fires after parsing when set to true.

Let’s create a simple function to call immediately after parsing to hide the overlay. It can be as simple as setting the CSS property “display” to “none”:

	var hideLoader = function(){
		dojo.style("preloader", "display", "none");
	}
	dojo.addOnLoad(function(){
		dojo.parser.parse();
		hideLoader();
	});

A preview of this step: Simply hiding the overly when ready.

It can also be something more aesthetically pleasing, like a fadeOut call. Fading out a node doesn’t affect the ‘display’ property at all, which we’ll need to set to ‘none’ to allow clicks and interaction, as the overlay is actually still in place, just hidden. We can replace our hideLoader function with a simple animation:

	var hideLoader = function(){
		dojo.fadeOut({
			node:"preloader",
			onEnd: function(){
				dojo.style("preloader", "display", "none");
			}
		}).play();
	}

The next optimization we can do involves a small code change. If no dojo.require() calls are made before the DOM is ready, addOnLoad will fire immediately. This works to our advantage here: by loading the simple 26KB dojo.js only, we’re given a really strong set of APIs, without ever including any Dijit components. Let’s defer the loading of the Dijit files until after the DOM is done (ensuring our overlay is up and spinning before ANY XHRs take place). Simply wrap them in an addOnLoad function, still defining our hideLoader function, though this time calling it from within an embedded onLoad function:

	

The end result of our trivial code change can be seen in the after onLoad example.

dojo.addOnLoad is smarter (or at the very least does more) than body.onLoad / document.ready / et al. It knows when Dojo modules are in flight or otherwise being requested, and re-fires after all dependencies have been solved. You can use this technique over and over as often as you like. If a module is already ready, dojo.require() is a no-op, and any subsequent dojo.addOnLoad calls will fire relatively quickly.

That’s all there is to it! We’re still using 92 requests (43 from the CDN), and the same byte count on code, and we’ve even actually slowed down the page loading by 700ms (the duration of the fadeOut animation) but perceived speed is speed, and this simply feels a lot faster. Once we’re done developing this page, we can move on into creating a build to limiting the number of requests and concatenate all the CSS together in one fell swoop. The key here is giving the user the sensation of “working”. The loading indicator screams “bear with me, I’ve not left you hanging.”

A designer with good CSS skills can certainly style the content within the preloader node using any standard techniques, customizing the feel with ease, or a developer can create a more riveting animation to hide it. Anything is possible in with the new 1.2 release of the Dojo Toolkit. The Base 26KB dojo.js provides all the utilities needed for Animation, Events, Ajax, Package Loading, Styling, and Node Manipulation, Object orientation, JavaScript lang utilities and the Dijit add-ons can be deferred until much later in a page life cycle to accelerate page load time and application responsiveness.

Comments

  • Amazing!

    It is *almost* a Office XP looking page in 5 minutes. To not say app, that would take just a little more with functionalities.

    Thanks.

  • Bin Hu

    Great article. I am looking forward to your article on custom building of Dojo.

  • erick2red

    Nicely done.

  • Peter you rule. This and the custom build explanation, http://www.sitepen.com/blog/2008/04/02/dojo-mini-optimization-tricks-with-the-dojo-toolkit/, have been really helpful in getting good stuff out the door.

  • This is really cool but there is a slight error.
    The loading.gif in the example did not exist.
    I checked my own dojo1.2 and found you had the url slightly wrong.
    Missing the images/ before the loading.gif.
    Should be.
    dojox/image/resources/images/loading.gif
    If you fix it in this example, it should pretty much cut and paste and work right away.

  • Keyton Weissinger

    Hi Peter,

    Thank you very much for writing this. Well done.

    Quick question. In using this on my own, I get the preloader screen to come up properly but that it’s just shown ABOVE my un-parsed HTML rather than OVER it.

    So for the time I see the spinner, I can just go over to the right, grab the scroll bar that is there, scroll down and see some hideous unparsed HTML. For whatever reason it doesn’t look like the preloader div is displaying OVER/ONTOP of my stuff.

    Any ideas?

    Thank you very much!

    Best,
    Keyton

  • JM Rigade

    Hi,
    cool work, thank you.

    But I’ve some Dojo dialog, and if I change some liste box, an Ajax call is made, but without refresh page.

    So I’ve not waiting animation during ajax request (BDD and so on).
    How lock and grey dialog during Ajax request ?

  • Pingback: Web Phrontistery » DOJO: Flashing of Unstyled Content (FOUC) in Dijit Components()

  • Hi, it’s a great article with great tipps and ideas involved – thank you for that!

    One tiny problem though:
    If a user has Javascript disabled, nothing would appear besides the loading animation. One great architectural aspects of Dojo is that the page would (normally) even work without JavaScript. In this case, it doesn’t because the #preloader will not be hidden and the page would absolutely be useless.

    There might be a workaround with setting the css property to display:none in some area like:

    #preloader { display:none;}

    Regards from Germany,
    Lasse

  • Hi,

    next try regarding my previous comment:

    “some area like” should read “some ‘noscript’ area” like

    <noscript>
    <style type =”text/css”>
    #preloader { idsplay:none }
    </style>
    </noscript>

  • Updated the example to use Dojo 1.5 and Claro theme:

    http://dante.dojotoolkit.org/static/xd/preloader-15.html

    0 code changes required, 1 optional (onEnd passes target node to callback now)

  • Would it be possible to encapsulate this functionality into a custom widget? The only thing that seems tricky is being able to tap into the addOnLoad from within the widget.
    Any thoughts?

  • Al Reno

    At first read it was a nice idea; unfortunately it does not seem to work with dojox.mobile.parser (unless you also require dojo.parser which obviously would be overkill in that situation). Too bad, A.R.

  • @Al, it’s a very old example. It could be updated and made to work with dojox.mobile.parser, but this example was created years before Dojo Mobile existed…