Flicker free initialization that degrades gracefully
One big issue I've found with various jQuery UI widgets and other effects if that they cause a "browser flash" on initialization, a prime example being how for tabs all the content is visible until the tab initializes and then all the non-active tabs vanish.
One way around this is to add the jQuery UI classes manually in your markup so that the tabset appears the same regardless of whether or not the tabs have been initialized, but this does not degrade gracefully and leaves users without javascript unable to access the content in the non-active tabs.
Recently I was reading about Javascript techniques for manipulating styles, and one of the things mentioned was programatically adding <link> tags to the document head. After a bit of experimentation I found that this trick worked even if the page hadn't finished loading and the DOM wasn't initialized yet. After some further experimenting I came up with a way of getting the tabs to be nicely formatted and not flash on document.ready, while still having all the tab content be available to non-javascript users.
1> Create a jQuery plugin, I've called mine jquery.loadcss.js. Here's the source code:
jQuery.loadCss = function (url)
{
var cssNode = document.createElement('link');
cssNode.type = 'text/css';
cssNode.rel = 'stylesheet';
cssNode.href = url;
cssNode.media = 'screen';
cssNode.title = 'dynamicLoadedSheet';
cssNode.id = 'dynamicCss';
document.getElementsByTagName ("head")[0].appendChild (cssNode);
};
2> If you have not already done so, rework your HTML code so that all the panels in your tabs have something in common, such as a class. In my HTML all panels that will be tabs have a class .tabbertab.
3> create a stylesheet which holds rules to initialize your tabs. I've written one that hides all tabs except the first one. I named this file dynamic.css. The code is as follows:
.tabbertab ~ .tabbertab {
display:none;
}
This probably won't work in IE6 but if you need IE6 compatibility you can probably come up with some different styling rules.
4> put jquery.js and the loadcss plugin in your document head.
5> Put an inline javascript in your head after the jQuery and plugin scripts. DON'T set this to fire on document.ready otherwise all benefit is lost!
<script type="text/javascript">
//<![CDATA[
$.loadCss ('templates/interface/styles/dynamic.css');
//]]>
</script>
6> At the bottom of the page along with all your other scripts, put a jQuery remove() statement after your tabs() call to get rid of the stylesheet. Attach this one to the document.ready event
$(function () {$('#dynamicCss').remove ();});
When your page loads the browser will execute the loadCss () call immediately and cause the dynamic.css file to be attached to the document head. This works in spite of the fact the document isn't fully loaded (I tested this in all versionf of IE from 6 onwards, and in the latest versions of FireFox, Safari, Opera and Chrome). All .tabbertab elements that aren't the first child in their group will be hidden.
Later on, when you've initialized the tabs on document.ready, you need to remove the stylesheet that's keeping all the non-active tabs hidden. Once that's done by using remove() your tabs will behave just as they would normally. You won't get a browser flash as the tabs are initialized, and if your viewer has javascript turned off, all the content in all the tabs will still be available as the stylesheet to hide the non-active tabs won't load.
This technique will probably need some refinement, but it seems to work well. It has all kinds of other potential uses too.