I need to load a bunch of CSS files through ajax and call an animation when the stylesheet has finished loading, otherwise the animation will fail.
What I have done so and used to work pretty well until I came accross doing this cross-domain is this:
$.get(resource.url, {cache:true}, function(css) {
//Now that the stylesheet is in the browser cache, it will load instantly:
$("head").append($("<link>",{
rel: "stylesheet",
type: "text/css",
href: resource.url
}));
}).then(function(){
//Animation here that depends on the loaded css
});
This works fine as long as resource.url is on the same domain. Once I try to load the css from another domain $.get will fail like this:
XMLHttpRequest cannot load https://example.com/style.css. Origin https://example.com is not allowed by Access-Control-Allow-Origin.
So I have tried to add CORS into the header through .htaccess:
<IfModule mod_headers.c>
#cross domain access is okay for resources (#107)
<FilesMatch "\.(css|js)$">
Header add Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
This adds the CORS header to all CSS and JS resources.
For some reason CORS doesn’t seem to have an effect on either chrome or firefox (newest versions).
I also came to notice that same domain policy is not enforced when doing $.getScript for js files, but it is for $.get:
$.get("https://example.com/script.js", {cache: false}, $.noop, "script");
//works regardless of CORS
but:
$.get("https://example.com/script.js", {cache: false}, $.noop);
//does not work (cross domain policy violation)
So since CORS is not widely supported and doesn’t even seem solve the problem for a modern browser, I need something that behaves like $.getScript, but for CSS stylesheets.
It needs to be asynchronous and have a callback mechanism.
Any ideas? Thanks in advance…
$.getuses Ajax, which must obey the Same-Origin Policy.$.getScriptnormally uses Ajax, but it also has a fallback option for cross-domain use only. Scripts imported via<script>tag are not subject to Same-Origin rules, so jQuery just adds a<script>tag to the page and sets itssrcattribute to the requested script URL.The same exemption is made for CSS resources loaded in through
<link>tags. In a perfect world, you should be able to 1) make a new<link>element, 2) set itshrefattribute to the right URL and 3) listen for aloadevent on that element. I’ve added a callback to this solution from the jQuery forums:One small problem here: it doesn’t work cross-browser.
<link>tags do not fireloadevents in all browsers — see the jQuery bug report for the$.getCSSfunction that could have been.So, the general-case workaround is a bit insane: add the CSS URL as the source of a new
<img>tag and listen for itsonerrorhandler:You could also add a bit of optimization and listen for
loadevent on the<link>(for browsers that support it) and anerrorevent on the<img>(for those that don’t), and put some logic in place to ensure the callback is only ever called once, in case both events occur.As for making
$.getCSSreturn a deferred object, that’s a bit out of my area of expertise, but there’s no theoretical reason why it couldn’t be done.