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

javascript

Solution

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.

Problem

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 :)

Original source