2

I'm trying to load additional css file using code like this:

var doc = document,
    head = doc.getElementsByTagName('head')[0],
    link = doc.createElement('link'),
    file = link.cloneNode(true);

file.type = 'text/css';
file.rel = 'stylesheet';

file.onload = function () {
    alert('css file is loaded!');
};
file.onerror = function () {
    // 404 error
    alert('Script ' + url + ' wasn\'t loaded! Check file URL');
};

file.href = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css';
head.appendChild(file);

http://jsfiddle.net/d3bcp4dy/1/

It's perfectly works in CH, FF, Opera 20+, etc.,

but it doesn't work in Safari5.1, IOS 5.1, Android 4.2 and less!

Why onload/onerror events don't work for .css file?

p.s. If I change file to .js - onload or onerror event works.

7
  • 1
    look at developer.mozilla.org/en/docs/Web/HTML/Element/… - seems it's just the way it is Commented Nov 16, 2015 at 12:38
  • @JaromandaX: I'm seeing ?, not "not supported," for the ones the OP is asking about... Commented Nov 16, 2015 at 12:41
  • clearly MDN don't know - and from the evidence above, one can assume it's not supported - and I do know what happens when one assumes Commented Nov 16, 2015 at 12:42
  • fortunately, https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css is CORS enabled, so you can use XMLHttpRequest, or even, fetch (polyfills for fetch and Promise available for internet exploder) to load the css, and stick it in a <style> tag Commented Nov 16, 2015 at 12:44
  • @T.J.Crowder True, but there is another link below that which defines the behavior for iOS/Android - pie.gd/test/script-link-events Commented Nov 16, 2015 at 12:46

2 Answers 2

2

If notification is unreliable, you can poll to see the new stylesheet arrive, see comments:

(function() {
    // Remember how many stylesheets there are
    var old = document.styleSheets.length;

    // Set a timeout
    var timeout = Date.now() + 30000;

    // Watch for new arrivals
    var timer = setInterval(function() {
        if (document.styleSheets.length > old) {
            console.log("Got it! " + document.styleSheets.length);
            clearInterval(timer);
        } else if (Date.now() > timeout) {
            console.log("Give up");
            clearInterval(timer);
        }
    }, 100);

    // Add the stylesheet link
    var link = document.createElement('link');
    link.rel = "stylesheet";
    link.href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css";
    link.onload = function() {
        console.log("Got it, clearing timer");
        clearInterval(timer);
        // ...
    };
    link.onerror = function() {
        console.log("Got error, clearing timer");
        clearInterval(timer);
        // ...
    };
    document.querySelector('head').appendChild(link);
})();

The advantage to this over using an ajax request is that you don't need CORS.

Note: I used Date.now above for convenience, you'll need to shim/polyfill it (or not use it) on some of the browsers you mention. The shim/polyfill is trivial:

if (!Date.now) {
    Date.now = function() {
        return +new Date;
    };
}
Sign up to request clarification or add additional context in comments.

Comments

1

fortunately, https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css is CORS enabled, so you can use XMLHttpRequest, or even, fetch

Using fetch

fetch('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css')
.then(function(response) {
    return response.text();
})
.then(function(text) {
    var style = document.head.appendChild(document.createElement('style'));
    style.textContent = text;
    console.log('style loaded');
}).catch(function(err) {
    console.error('style load failed with error', err);
});

Polyfill for fetch - https://github.com/github/fetch you'll probably also need a polyfill for Promise if you need one for fetch - https://www.promisejs.org/#browser

You can use XMLHttpRequest too, if you want

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css');
xhr.addEventListener('load', function() {
    console.log('style loaded', this.responseText);
});
xhr.addEventListener('error', function(e) {
    console.error('style load failed');
});
xhr.send();

And if you are writing for browsers from the stone age, there are ways to achieve the same thing using ActiveX rubbish and some weird cross domain hack in internet explorer - use it or whatever

8 Comments

"You can use XMLHttpRequest too, if you want" Well, not on IE8 or IE9. :-)
I stopped caring about windows XP years ago - if you want to run XP, don't use IE - simple solution
Seeing as the OP doesn't even mention internet exploder, then you have a cows opinion :p
Yeah, the problem is, it's not up to you (or me), and people still use the darned thing, the fools. The OP's post is quite clearly about supporting old browsers. (Nice Friends reference! I love that scene.)
Maybe next year - yeah, I remember hearing that about IE6 for too many years.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.