9271f9c6e942b68a4fbfa228f67ab46b72c76780Ryan Grove/*jslint boss:true, expr:true, laxbreak: true */
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveProvides dynamic loading of remote JavaScript and CSS resources.
28b0543efe5da1a7aba6d4c453343ee509949bf9Ryan Grove CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Public Properties ----------------------------------------------------
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Default options for CSS requests. Options specified here will override
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove global defaults for CSS requests.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove See the `options` property for all available options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property cssOptions
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type Object
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Default options for JS requests. Options specified here will override global
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove defaults for JS requests.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove See the `options` property for all available options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property jsOptions
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type Object
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Default options to use for all requests.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Note that while all available options are documented here for ease of
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove discovery, some options (like callback functions) only make sense at the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction level.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Callback functions specified via the options object or the `options`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove parameter of the `css()`, `js()`, or `load()` methods will receive the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction object as a parameter. See `Y.Get.Transaction` for details on
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove the properties and methods available on transactions.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Object} options
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Boolean} [options.async=false] Whether or not to load scripts
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove asynchronously, meaning they're requested in parallel and execution
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove order is not guaranteed. Has no effect on CSS, since CSS is always
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove loaded asynchronously.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Object} [options.attributes] HTML attribute name/value pairs that
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove should be added to inserted nodes. By default, the `charset` attribute
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove will be set to "utf-8" and nodes will be given an auto-generated `id`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove attribute, but you can override these with your own values if desired.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Boolean} [options.autopurge] Whether or not to automatically
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove purge inserted nodes after the purge threshold is reached. This is
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove `true` by default for JavaScript, but `false` for CSS since purging a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove CSS node will also remove any styling applied by the referenced file.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Object} [options.context] `this` object to use when calling
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove callback functions. Defaults to the transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Mixed} [options.data] Arbitrary data object to pass to "on*"
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Document} [options.doc] Document into which nodes should be
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove inserted. By default, the current document is used.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {HTMLElement|String} [options.insertBefore] HTML element or id
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove string of an element before which all generated nodes should be
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove inserted. If not specified, Get will automatically determine the best
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove place to insert nodes for maximum compatibility.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Function} [options.onEnd] Callback to execute after a transaction
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove is complete, regardless of whether it succeeded or failed.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Function} [options.onFailure] Callback to execute after a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction fails, times out, or is aborted.
76ec8d54f0bcedc166ad8c440a4696eca78c91e3Ryan Grove @property {Function} [options.onProgress] Callback to execute after each
76ec8d54f0bcedc166ad8c440a4696eca78c91e3Ryan Grove individual request in a transaction either succeeds or fails.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Function} [options.onSuccess] Callback to execute after a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction completes successfully with no errors. Note that in browsers
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove that don't support the `error` event on CSS `<link>` nodes, a failed CSS
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove request may still be reported as a success because in these browsers
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove it can be difficult or impossible to distinguish between success and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove failure for CSS resources.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Function} [options.onTimeout] Callback to execute after a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction times out.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Number} [options.pollInterval=50] Polling interval (in
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove milliseconds) for detecting CSS load completion in browsers that don't
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove support the `load` event on `<link>` nodes. This isn't used for
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Number} [options.purgethreshold=20] Number of nodes to insert
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove before triggering an automatic purge when `autopurge` is `true`.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {Number} [options.timeout] Number of milliseconds to wait before
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove aborting a transaction. When a timeout occurs, the `onTimeout` callback
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove is called, followed by `onFailure` and finally `onEnd`. By default,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove there is no timeout.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property {String} [options.type] Resource type ("css" or "js"). This option
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove is set automatically by the `css()` and `js()` functions and will be
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove ignored there, but may be useful when using the `load()` function. If
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove not specified, the type will be inferred from the URL, defaulting to
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove "js" if the URL doesn't contain a recognizable file extension.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Protected Properties -------------------------------------------------
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Regex that matches a CSS URL. Used to guess the file type when it's not
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property REGEX_CSS
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type RegExp
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Regex that matches a JS URL. Used to guess the file type when it's not
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property REGEX_JS
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type RegExp
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Contains information about the current environment, such as what script and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove link injection features it supports.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This object is created and populated the first time the `_getEnv()` method
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property _env
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type Object
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove Mapping of document _yuid strings to <head> or <base> node references so we
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove don't have to look the node up each time we want to insert a request node.
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove @property _insertCache
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove @type Object
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Information about the currently pending transaction, if any.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This is actually an object with two properties: `callback`, containing the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove containing the actual transaction instance.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property _pending
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type Object
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove HTML nodes eligible to be purged next time autopurge is triggered.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property _purgeNodes
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type HTMLElement[]
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Queued transactions and associated callbacks.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property _queue
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type Object[]
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Public Methods -------------------------------------------------------
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Aborts the specified transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This will cause the transaction's `onFailure` callback to be called and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove will prevent any new script and link nodes from being added to the document,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove but any resources that have already been requested will continue loading
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove (there's no safe way to prevent this, unfortunately).
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove *Note:* This method is deprecated as of 3.5.0, and will be removed in a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove future version of YUI. Use the transaction-level `abort()` method instead.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method abort
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Get.Transaction} transaction Transaction to abort.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @deprecated Use the `abort()` method on the transaction instead.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('`Y.Get.abort()` is deprecated as of 3.5.0. Use the `abort()` method on the transaction instead.', 'warn', 'get');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove for (i = 0, len = this._queue.length; i < len; ++i) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Loads one or more CSS files.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove The _urls_ parameter may be provided as a URL string, a request object,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove or an array of URL strings and/or request objects.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove A request object is just an object that contains a `url` property and zero
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove or more options that should apply specifically to that request.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Request-specific options take priority over transaction-level options and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove default options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove URLs may be relative or absolute, and do not have to have the same origin
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove as the current page.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove The `options` parameter may be omitted completely and a callback passed in
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove its place, if desired.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Load a single CSS file and log a message on completion.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.Get.css('foo.css', function (err) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('foo.css failed to load!');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('foo.css was loaded successfully');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Load multiple CSS files and log a message when all have finished
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.Get.css(urls, function (err) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('one or more files failed to load!');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('all files loaded successfully');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Specify transaction-level options, which will apply to all requests
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // within the transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.Get.css(urls, {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove attributes: {'class': 'my-css'},
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove timeout : 5000
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Specify per-request options, which override transaction-level and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // default options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove {url: 'foo.css', attributes: {id: 'foo'}},
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {String|Object|Array} urls URL string, request object, or array
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove of URLs and/or request objects to load.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Object} [options] Options for this transaction. See the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove `Y.Get.options` property for a complete list of available options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Function} [callback] Callback function to be called on completion.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This is a general callback and will be called before any more granular
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove @param {Array|null} callback.err Array of errors that occurred during
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove the transaction, or `null` on success.
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove @param {Get.Transaction} callback.transaction Transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @return {Get.Transaction} Transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove return this._load('css', urls, options, callback);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Loads one or more JavaScript resources.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove The _urls_ parameter may be provided as a URL string, a request object,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove or an array of URL strings and/or request objects.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove A request object is just an object that contains a `url` property and zero
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove or more options that should apply specifically to that request.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Request-specific options take priority over transaction-level options and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove default options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove URLs may be relative or absolute, and do not have to have the same origin
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove as the current page.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove The `options` parameter may be omitted completely and a callback passed in
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove its place, if desired.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Scripts will be executed in the order they're specified unless the `async`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove option is `true`, in which case they'll be loaded in parallel and executed
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove in whatever order they finish loading.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Load a single JS file and log a message on completion.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.Get.js('foo.js', function (err) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('foo.js failed to load!');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('foo.js was loaded successfully');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Load multiple JS files, execute them in order, and log a message when
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // all have finished loading.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.Get.js(urls, function (err) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('one or more files failed to load!');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('all files loaded successfully');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Specify transaction-level options, which will apply to all requests
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // within the transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove attributes: {'class': 'my-js'},
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove timeout : 5000
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Specify per-request options, which override transaction-level and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // default options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove {url: 'foo.js', attributes: {id: 'foo'}},
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {String|Object|Array} urls URL string, request object, or array
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove of URLs and/or request objects to load.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Object} [options] Options for this transaction. See the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove `Y.Get.options` property for a complete list of available options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Function} [callback] Callback function to be called on completion.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This is a general callback and will be called before any more granular
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove @param {Array|null} callback.err Array of errors that occurred during
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove the transaction, or `null` on success.
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove @param {Get.Transaction} callback.transaction Transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @return {Get.Transaction} Transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove return this._load('js', urls, options, callback);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Loads one or more CSS and/or JavaScript resources in the same transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Use this method when you want to load both CSS and JavaScript in a single
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction and be notified when all requested URLs have finished loading,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove regardless of type.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Behavior and options are the same as for the `css()` and `js()` methods. If
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove a resource type isn't specified in per-request options or transaction-level
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove options, Get will guess the file type based on the URL's extension (`.css`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove or `.js`, with or without a following query string). If the file type can't
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove be guessed from the URL, a warning will be logged and Get will assume the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove URL is a JavaScript resource.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Load both CSS and JS files in a single transaction, and log a message
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // when all files have finished loading.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('one or more files failed to load!');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('all files loaded successfully');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method load
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {String|Object|Array} urls URL string, request object, or array
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove of URLs and/or request objects to load.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Object} [options] Options for this transaction. See the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove `Y.Get.options` property for a complete list of available options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Function} [callback] Callback function to be called on completion.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This is a general callback and will be called before any more granular
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Array|null} err Array of errors that occurred during the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction, or `null` on success.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Get.Transaction} Transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @return {Get.Transaction} Transaction object.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove return this._load(null, urls, options, callback);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Protected Methods ----------------------------------------------------
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Triggers an automatic purge if the purge threshold has been reached.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method _autoPurge
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Number} threshold Purge threshold to use, in milliseconds.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (threshold && this._purgeNodes.length >= threshold) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('autopurge triggered after ' + this._purgeNodes.length + ' nodes', 'info', 'get');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Populates the `_env` property with information about the current
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove environment.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method _getEnv
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @return {Object} Environment information.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @since 3.5.0
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove _getEnv: function () {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Note: some of these checks require browser sniffs since it's not
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // feasible to load test files on every pageview just to perform a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // feature test. I'm sorry if this makes you sad.
9271f9c6e942b68a4fbfa228f67ab46b72c76780Ryan Grove return (this._env = {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // True if this is a browser that supports disabling async mode on
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // dynamically created script nodes. See
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // https://developer.mozilla.org/En/HTML/Element/Script#Attributes
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove async: doc && doc.createElement('script').async === true,
ec517250becaa7a1d3705f1883714ce0f851a047Ryan Grove // True if this browser fires an event when a dynamically injected
ec517250becaa7a1d3705f1883714ce0f851a047Ryan Grove // link node fails to load. This is currently true for Firefox 9+
ec517250becaa7a1d3705f1883714ce0f851a047Ryan Grove // and WebKit 535.24+.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // True if this browser fires an event when a dynamically injected
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // link node finishes loading. This is currently true for IE, Opera,
8102ade9453db9ab849be45d2a29db1c0392216bRyan Grove // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
8102ade9453db9ab849be45d2a29db1c0392216bRyan Grove // DOM 0 "onload" event, but not "load". All versions of IE fire
8102ade9453db9ab849be45d2a29db1c0392216bRyan Grove // "onload".
f946e1b4c7a36ceab0d433a6a03f882b9d57ac87Dav Glass // davglass: Seems that Chrome on Android needs this to be false.
f946e1b4c7a36ceab0d433a6a03f882b9d57ac87Dav Glass ua.gecko >= 9 || ua.webkit >= 535.24) && !(ua.chrome && ua.chrome <=18),
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // True if this browser preserves script execution order while
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // loading scripts in parallel as long as the script node's `async`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // attribute is set to false to explicitly disable async execution.
b52c03f5025527238b00613e32abb705eeb618f7Ryan Grove // Clone the attributes object so we don't end up modifying it by ref.
7bdddcbe121d987f4884bb016777b7fecdc76742Ryan Grove options.attributes = Y.merge(this.options.attributes,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // If `url` is a string, we create a URL object for it, then mix in
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // global options and request-specific options. If it's an object
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // with a "url" property, we assume it's a request object containing
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // URL-specific options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // URL-specific options override both global defaults and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // request-specific options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove url = url.url; // Make url a string so we can use it later.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('URL must be a string or an object with a `url` property.', 'error', 'get');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // If we didn't get an explicit type for this URL either in the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // request options or the URL-specific options, try to determine
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // one from the file extension.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log("Can't guess file type from URL. Assuming JS: " + url, 'warn', 'get');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Mix in type-specific default options, but don't overwrite any
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // options that have already been set.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove false, null, 0, true);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Give the node an id attribute if it doesn't already have one.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove req.attributes.id || (req.attributes.id = Y.guid());
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Backcompat for <3.5.0 behavior.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('The `win` option is deprecated as of 3.5.0. Use `doc` instead.', 'warn', 'get');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove req.win = req.doc.defaultView || req.doc.parentWindow;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.log('The `charset` option is deprecated as of 3.5.0. Set `attributes.charset` instead.', 'warn', 'get');
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove _load: function (type, urls, options, callback) {
9271f9c6e942b68a4fbfa228f67ab46b72c76780Ryan Grove // Allow callback as third param.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (!this._env) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove transaction = this._getTransaction(urls, options);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove _next: function () {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove item.callback && item.callback.apply(this, arguments);
3cc83e7d5c1cc1f2e9e60efaec0584e22ae52800Ryan Grove // Don't purge nodes that haven't finished loading (or errored out),
3cc83e7d5c1cc1f2e9e60efaec0584e22ae52800Ryan Grove // since this can hang the transaction.
9271f9c6e942b68a4fbfa228f67ab46b72c76780Ryan Grove node.parentNode && node.parentNode.removeChild(node);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // If this is a transaction-level purge and this node also exists in
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // the Get-level _purgeNodes array, we need to remove it from
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // _purgeNodes to avoid creating a memory leak. The indexOf lookup
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // sucks, but until we get WeakMaps, this is the least troublesome
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // way to do this (we can't just hold onto node ids because they may
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // not be in the same document).
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveAlias for `js()`.
b5276e211acea576c3d3edc6aaccd94a8fc4402aRyan Grove@method script
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveRepresents a Get transaction, which may contain requests for one or more JS or
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveThis class should not be instantiated manually. Instances will be created and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grovereturned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@class Get.Transaction
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveGet.Transaction = Transaction = function (requests, options) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove self._callbacks = []; // callbacks to call after execution finishes
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Deprecated pre-3.5.0 properties.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveArbitrary data object associated with this transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveThis object comes from the options passed to `Get.css()`, `Get.js()`, or
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove`Get.load()`, and will be `undefined` if no data object was specified.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {Object} data
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveArray of errors that have occurred during this transaction, if any.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {Object[]} errors
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {String} errors.error Error message.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {Object} errors.request Request object related to the error.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveNumeric id for this transaction, unique among all transactions within the same
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveYUI sandbox in the current pageview.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {Number} id
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveHTMLElement nodes (native ones, not YUI Node instances) that have been inserted
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Groveduring the current transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {HTMLElement[]} nodes
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveOptions associated with this transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveSee `Get.options` for the full list of available options.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {Object} options
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveRequest objects contained in this transaction. Each request object represents
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Groveone CSS or JS URL that will be (or has been) requested and loaded into the page.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property {Object} requests
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan GroveId of the most recent transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove@property _lastId
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Public Properties ----------------------------------------------------
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Current state of this transaction. One of "new", "executing", or "done".
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @property _state
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @type String
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Public Methods -------------------------------------------------------
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Aborts this transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove This will cause the transaction's `onFailure` callback to be called and
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove will prevent any new script and link nodes from being added to the document,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove but any resources that have already been requested will continue loading
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove (there's no safe way to prevent this, unfortunately).
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method abort
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {String} [msg="Aborted."] Optional message to use in the `errors`
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove array describing why the transaction was aborted.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Begins execting the transaction.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove There's usually no reason to call this manually, since Get will call it
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove automatically when other pending transactions have finished. If you really
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove want to execute your transaction before Get does, you can, but be aware that
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove this transaction's scripts may end up executing before the scripts in other
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove pending transactions.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove If the transaction is already executing, the specified callback (if any)
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove will be queued and called after execution finishes. If the transaction has
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove already finished, the callback will be called immediately (the transaction
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove will not be executed again).
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method execute
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @param {Function} callback Callback function to execute after all requests
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove in the transaction are complete, or after the transaction is aborted.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove callback && callback(self.errors.length ? self.errors : null, self);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove for (i = 0, len = requests.length; i < len; ++i) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // No need to queue CSS or fully async JS.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Manually purges any `<script>` or `<link>` nodes this transaction has
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Be careful when purging a transaction that contains CSS requests, since
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove removing `<link>` nodes will also remove any styles they applied.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove @method purge
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove purge: function () {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // -- Protected Methods ----------------------------------------------------
28b0543efe5da1a7aba6d4c453343ee509949bf9Ryan Grove // IE6 and IE7 expect property names rather than attribute names for
28b0543efe5da1a7aba6d4c453343ee509949bf9Ryan Grove // certain attributes. Rather than sniffing, we do a quick feature
28b0543efe5da1a7aba6d4c453343ee509949bf9Ryan Grove // test the first time _createNode() runs to determine whether we
28b0543efe5da1a7aba6d4c453343ee509949bf9Ryan Grove // need to provide a workaround.
28b0543efe5da1a7aba6d4c453343ee509949bf9Ryan Grove node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove _finish: function () {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove var errors = this.errors.length ? this.errors : null,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove for (i = 0, len = this._callbacks.length; i < len; ++i) {
70fce8db583722b79c5c4391f2b16cb60324656bDav Glass if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // This merge is necessary for backcompat. I hate it.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove return Y.merge(this, {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove abort : this.abort, // have to copy these because the prototype isn't preserved
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove return this;
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove return typeof el === 'string' ? doc.getElementById(el) : el;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Inserting before a <base> tag apparently works around an IE bug
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // bug that is, exactly. Better safe than sorry?
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove if ((el = doc.getElementsByTagName('base')[0])) { // assignment
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove // Look for a <head> element.
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove el = doc.head || doc.getElementsByTagName('head')[0];
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove // Create a marker node at the end of <head> to use as an insertion
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove // point. Inserting before this node will ensure that all our CSS
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove // gets inserted in the correct order, to maintain style precedence.
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove // If all else fails, just insert before the first script node on the
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove // page, which is virtually guaranteed to exist.
d716da5e4c4ab0f8892a0eee0414a9643253a477Ryan Grove return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove node = req.node = this._createNode(nodeType, req.attributes,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove self._progress('Failed to load ' + req.url, req);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove function onLoad() {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Deal with script asynchronicity.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Explicitly indicate that we want the browser to execute this
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // script asynchronously. This is necessary for older browsers
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // like Firefox <4.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // This browser treats injected scripts as async by default
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // (standard HTML5 behavior) but asynchronous loading isn't
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // desired, so tell the browser not to mark this script as
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // If this browser doesn't preserve script execution order based
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // on insertion order, we'll need to avoid inserting other
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // scripts until this one finishes loading.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // In Firefox <9, we can import the requested URL into a <style>
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // node and poll for the existence of node.sheet.cssRules. This
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // gives us a reliable way to determine CSS load completion that
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // also works for cross-domain stylesheets.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Props to Zach Leatherman for calling my attention to this
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // technique.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove '@charset "' + req.attributes.charset + '";' : '') +
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Inject the node.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Script on IE6, 7, and 8.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // CSS on Firefox <9 or WebKit.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Script or CSS on everything else. Using DOM 0 events because that
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // evens the playing field with older IEs.
ec517250becaa7a1d3705f1883714ce0f851a047Ryan Grove // If this browser doesn't fire an event when CSS fails to load,
ec517250becaa7a1d3705f1883714ce0f851a047Ryan Grove // fail after a timeout to avoid blocking the transaction queue.
ec517250becaa7a1d3705f1883714ce0f851a047Ryan Grove cssTimeout = setTimeout(onError, req.timeout || 3000);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove insertBefore.parentNode.insertBefore(node, insertBefore);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove _next: function () {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // If there are requests in the queue, insert the next queued request.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Otherwise, if we're waiting on already-inserted requests to finish,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // wait longer. If there are no queued requests and we're not waiting
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // for anything to load, then we're done!
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove } else if (!this._waiting) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove pendingCSS || (pendingCSS = self._pendingCSS = []);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // A poll timeout is already pending, so no need to create a
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // will still be treated as a success. There's no good workaround for
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Look for a stylesheet matching the pending URL.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove while (--j >= 0) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Many thanks to Zach Leatherman for calling my attention to
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // the @import-based cross-domain technique used here, and to
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Oleg Slobodskoi for an earlier same-domain implementation.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // See Zach's blog for more details:
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // We don't really need to store this value since we never
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // use it again, but if we don't store it, Closure Compiler
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // assumes the code is useless and removes it.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // If we get here, the stylesheet has loaded.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove } catch (ex) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // An exception means the stylesheet is still loading.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // Pre-3.5.0 Get always excludes the most recent node from an
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // autopurge. I find this odd, but I'm keeping that behavior for
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // the sake of backcompat.