If you have already developed RIAs with the focus of javascript client side programming, you might have come across the problem to execute some lines of code (normally wrapped in a callback function) after your JS lib is loaded completely. this is solved very nice with jQuery $.getScript function and its callback parameter.
But what about CSS? If you load your new CSS dynamically and want to make some DOM manimulations or design adjustments after switching CSS according to the newly loaded CSS style, you need to call a callback function after your css is loaded completely. The solution that I applied is as follows.
Add you CSS link to the head of the document. When CSS load is finished it must be found in the DOM tree. If you can find it, grat, you can call your callback function :-) if not try it later, lets say in an interval of 5 ms. The time you see it in DOM, it is loaded completely and you can call your callback function.
Following is the JS code with jQuery:
window.lastStaticStyleSheetIndex = document.styleSheets.length-1;
window.loadedLinks = []; // append css link to the head of the document
appendCSSLinkToHead = function(url, title) {
var oLink = document.createElement("link")
oLink.href = url;
oLink.rel = "alternate stylesheet";
oLink.type = "text/css";
oLink.media = "screen";
oLink.title = title;
document.getElementsByTagName("head")[0].appendChild(oLink); window.loadedLinks.push(title);
}switchCssTo = function(url, title) {
if($.inArray(title, window.loadedLinks) == -1) {
appendCSSLinkToHead(url, title);
}
var css_num = window.lastStaticStyleSheetIndex;
$("link").filter("[title][rel*=stylesheet]").each(function(i) {
this.disabled = true;
this.disabled = (this.title != title);
if(!this.disabled) css_num+=i;
});
callCallBackFunc(css_num, 0);
}callCallBackFunc = function (b, t) {
/* apply only if the css is completely loded in DOM */
try {
// FF if css not loaded an exception is fired
if (document.styleSheets[b].cssRules) {
callBack();
}
// IE no exception is fired!!!
else {
if (document.styleSheets[b].rules && document.styleSheets[b].rules.length) {
callBack();
}
else {
callRecursive(50, b, t);
}
}
}
catch(e) {
//debug(e);debug('time: '+t)
callRecursive(50, b, t);
}
function callRecursive(n, b, t) {
// try max until n
if(t < n) {
// try each 5ms intervals
setTimeout(function() {
callCallBackFunc(b, t+5);
}, t+5);
}
}
} //------------------------------------callBack = function(){
// your code here
}switchCssTo("path/to/newCss/newCss.css", "newCss")
I should add here it is tested only on IE8 and FF3+
I appreciate any other ideas and solutions or suggestions. Let me know if you have an idea on this issue :-)