Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript onload callback for "type" or "rel", 'text/plain' on script or link tag

Tags:

javascript

Why isn't onload fired for script type="text/plain" ? loadPlain below doesn't fire the callback, but loadScript does.

I expected this to work... should it not?

    loadPlain("http://localhost/ajax/libs/jquery/1.10.2/jquery.min.js", function(element) {
            alert(1);
            alert(element.innerHTML);
    }, undefined, {})

    function loadPlain(path, callback, errorCallback, options) {
            var element = document.createElement('script');
            element.setAttribute("type", 'text/plain');
            element.setAttribute("src", path);

            return loadBase(element, callback, errorCallback, options);
    }

    function loadScript(path, callback, errorCallback, options) {
            var element = document.createElement('script');
            element.setAttribute("type", 'text/javascript');
            element.setAttribute("src", path);

            return loadBase(element, callback, errorCallback, options);
    }


    function loadBase(element, callback, errorCallback, options) {
            element.loaded = false;

            if (element.readyState){  // IE
                    element.onreadystatechange = function(){
                            if (element.readyState == "loaded" || element.readyState == "complete"){
                                    element.onreadystatechange = null;

                                    loadBaseOnload(element, callback);
                            }
                    };
            } else {                 // Others
                    element.onload = function() {
                            loadBaseOnload(element, callback);
                    };
            }

            element.onerror = function() {
                    errorCallback && errorCallback(element);
            };

            (options.elementAppendTo || document.head || loadBase.head || (loadBase.head = document.getElementsByTagName('head')[0]) || document.body).appendChild(element);

            return element;
    }

    function loadBaseOnload(element, callback) {
            if (element.loaded != true) {
                    element.loaded = true;
                    if ( callback ) callback(element);
            }
    }

Please note that I know about XMLHttpRequest, but thats not the question :)

like image 378
mjs Avatar asked Jan 13 '23 17:01

mjs


2 Answers

The WHATWG (the organization who specifies browser behavior, alongside the W3C) has a list of known script MIME types and some blacklisted MIME types that must not be treated as scripting languages:

The following lists the MIME type strings that user agents must recognize, and the languages to which they refer:

  • "application/ecmascript"
  • "application/javascript"
  • "application/x-ecmascript"
  • ...

The following MIME types (with or without parameters) must not be interpreted as scripting languages:

  • "text/plain"
  • "text/xml"
  • "application/octet-stream"
  • "application/xml"

Note: These types are explicitly listed here because they are poorly-defined types that are nonetheless likely to be used as formats for data blocks, and it would be problematic if they were suddenly to be interpreted as script by a user agent.

What the WHATWG spec calls "data blocks" here are non-scripts enclosed in <script> tags:

In this example, two script elements are used. One embeds an external script, and the other includes some data.

<script src="game-engine.js"></script>
<script type="text/x-game-map">`
........U.........e
o............A....e
.....A.....AAA....e
.A..AAA...AAAAA...e
</script>

The components of the WHATWG spec that specify load events for <script> tags explicitly state that they fire for scripts referred to by <script> tags, not to non-script data blocks. A <script> element is a data block if its type is not recognized as a MIME type corresponding to a scripting language supported by the browser. This means that blacklisted types like text/plain will never be recognized as scripts, whereas type values in neither the must-support nor must-not-support list, like application/dart (for Google's Dart language) might be supported by some browsers.

Furthermore, including a non-script type alongside a src is not spec-compliant. Data blocks are legal only when specified inline:

When used to include data blocks (as opposed to scripts), the data must be embedded inline, the format of the data must be given using the type attribute, the src attribute must not be specified, and the contents of the script element must conform to the requirements defined for the format used.

like image 175
apsillers Avatar answered Jan 16 '23 00:01

apsillers


If you specify your script as "text/plain" the browser wont do anything with it.

You must specify it as "script/javascript" to have it execute as JavaScript.

like image 25
Halcyon Avatar answered Jan 16 '23 00:01

Halcyon