7

I want to detect if a script tag (that was dynamically created and added to the DOM) fails to load. The onerror event works, except with file:// URLs in Firefox.

Unfortunately none of the techniques described here (except timeouts, which are unacceptable in my case) seem to work in Firefox if the src of the script tag is a file:// URL (or relative URL and the page was loaded via a file:// URL)

Test case:

var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'doesnotexist.js');
script.onerror = function() { alert("Loading failed!"); }
document.getElementsByTagName('head')[0].appendChild(script);

Load this in an HTML page with a file:// URL. The onerror event won't execute in Firefox. Load from a webserver, or on Safari or Chrome, and it will.

This seems like a bug to me. Is there any known way around it?

3
  • 7
    You should accept answers to your questions.
    – SLaks
    Commented Nov 11, 2010 at 0:33
  • @Marcel Korpel: He said that timeouts are not an option, so that won't work. Commented Nov 11, 2010 at 1:30
  • 2
    For reference, the issue with Firefox not firing an error event when a file://-based URL fails to load is Bugzilla bug 621276.
    – Doug Paul
    Commented Aug 1, 2012 at 17:22

2 Answers 2

2
var loadScript = function(scriptURL, failureCallback) {
    var script = document.createElement('script'),
        scriptProtocol = scriptURL.match(/^([a-zA-Z]+:)\/\//);
    script.setAttribute('type', 'text/javascript');

    if (navigator.product === 'Gecko' &&
        navigator.userAgent.indexOf('KHTML') === -1 &&
        window.location.protocol === 'file:' &&
        (!scriptProtocol || scriptProtocol[1] === 'file:')) {

        var req = new XMLHttpRequest();
        req.open('GET', scriptURL, true);
        req.onreadystatechange = function () {
            if (req.readyState === 4) {
                if (req.status === 0)
                    script.textContent = req.responseText;
                else
                    failureCallback();
            }
        };
        try {
            req.send(null);
        }
        catch (e) {
            failureCallback();
        }
    }
    else {
        script.setAttribute('src', scriptURL);
        script.onerror = failureCallback; 
    }

    document.getElementsByTagName('head')[0].appendChild(script);
};

loadScript('doesnotexist.js', function() { alert('Loading failed!'); });

Bit of a hack, but it seems to work.

1
  • As Tom points out, a drawback of this method is that you lose debugging metadata for the script if it gets loaded via XHR. Commented Nov 12, 2010 at 0:19
1

What if you used Pauls solution to retrieve the document but ignored the result. If it loads the create your script tag. The downside is the file would load twice.

1
  • Yeah, this is the solution I went with for now, but I'm not happy about it ;)
    – tlrobinson
    Commented Nov 12, 2010 at 15:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.