The YUI Get Utility makes it easy to dynamically load CSS and JavaScript on demand, but there’s one tiny gotcha: Firefox, Safari, and other Gecko/WebKit-based browsers don’t provide a reliable way to tell when a CSS file has finished loading. As a result, when you load CSS in one of these browsers using the Get.css()
method, the onSuccess
callback is fired instantly.
In many cases this isn’t a problem, but if you need to ensure that you don’t perform an action (such as appending HTML to the page) until after the CSS has loaded, this can cause a race condition. There’s no way for the Get Utility to automatically work around this problem, but with a little bit of extra effort on our part, we can work around it ourselves.
The trick is to include a rule at the end of the dynamically-loaded CSS file that will send a message to our script by setting a style property on a special element. Once we see that property change, we know the CSS has finished loading.
First, the contents of our CSS file:
/* ... imagine lots of other CSS here ... */
#css-done { display: none; }
And now the JavaScript that will load it:
(function () {
var Y = YAHOO;
Y.util.Get.css('example.css', {
onSuccess: function () {
var el, poll;
function finished() {
alert('CSS has finished loading.');
}
if (Y.env.ua.gecko || Y.env.ua.webkit) {
el = document.body.appendChild(document.createElement('div'));
el.id = 'css-done';
poll = function () {
if (Y.util.Dom.getStyle(el, 'display') === 'none') {
// Once the element's display property changes, we know the CSS has
// finished loading.
el.parentNode.removeChild(el);
finished();
} else {
// The element's display property hasn't changed yet, so call this
// function again in 50ms.
setTimeout(poll, 50);
}
};
poll();
} else {
finished();
}
}
});
})();