diff -r d334a616c023 -r e16a97fb364a src/cm/media/js/lib/yui/yui3-3.15.0/build/get/get.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui3-3.15.0/build/get/get.js Mon Mar 10 15:19:48 2014 +0100 @@ -0,0 +1,1275 @@ +YUI.add('get', function (Y, NAME) { + +/*jslint boss:true, expr:true, laxbreak: true */ + +/** +Provides dynamic loading of remote JavaScript and CSS resources. + +@module get +@class Get +@static +**/ + +var Lang = Y.Lang, + + CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode() + + Get, Transaction; + +Y.Get = Get = { + // -- Public Properties ---------------------------------------------------- + + /** + Default options for CSS requests. Options specified here will override + global defaults for CSS requests. + + See the `options` property for all available options. + + @property cssOptions + @type Object + @static + @since 3.5.0 + **/ + cssOptions: { + attributes: { + rel: 'stylesheet' + }, + + doc : Y.config.linkDoc || Y.config.doc, + pollInterval: 50 + }, + + /** + Default options for JS requests. Options specified here will override global + defaults for JS requests. + + See the `options` property for all available options. + + @property jsOptions + @type Object + @static + @since 3.5.0 + **/ + jsOptions: { + autopurge: true, + doc : Y.config.scriptDoc || Y.config.doc + }, + + /** + Default options to use for all requests. + + Note that while all available options are documented here for ease of + discovery, some options (like callback functions) only make sense at the + transaction level. + + Callback functions specified via the options object or the `options` + parameter of the `css()`, `js()`, or `load()` methods will receive the + transaction object as a parameter. See `Y.Get.Transaction` for details on + the properties and methods available on transactions. + + @static + @since 3.5.0 + @property {Object} options + + @property {Boolean} [options.async=false] Whether or not to load scripts + asynchronously, meaning they're requested in parallel and execution + order is not guaranteed. Has no effect on CSS, since CSS is always + loaded asynchronously. + + @property {Object} [options.attributes] HTML attribute name/value pairs that + should be added to inserted nodes. By default, the `charset` attribute + will be set to "utf-8" and nodes will be given an auto-generated `id` + attribute, but you can override these with your own values if desired. + + @property {Boolean} [options.autopurge] Whether or not to automatically + purge inserted nodes after the purge threshold is reached. This is + `true` by default for JavaScript, but `false` for CSS since purging a + CSS node will also remove any styling applied by the referenced file. + + @property {Object} [options.context] `this` object to use when calling + callback functions. Defaults to the transaction object. + + @property {Mixed} [options.data] Arbitrary data object to pass to "on*" + callbacks. + + @property {Document} [options.doc] Document into which nodes should be + inserted. By default, the current document is used. + + @property {HTMLElement|String} [options.insertBefore] HTML element or id + string of an element before which all generated nodes should be + inserted. If not specified, Get will automatically determine the best + place to insert nodes for maximum compatibility. + + @property {Function} [options.onEnd] Callback to execute after a transaction + is complete, regardless of whether it succeeded or failed. + + @property {Function} [options.onFailure] Callback to execute after a + transaction fails, times out, or is aborted. + + @property {Function} [options.onProgress] Callback to execute after each + individual request in a transaction either succeeds or fails. + + @property {Function} [options.onSuccess] Callback to execute after a + transaction completes successfully with no errors. Note that in browsers + that don't support the `error` event on CSS `` nodes, a failed CSS + request may still be reported as a success because in these browsers + it can be difficult or impossible to distinguish between success and + failure for CSS resources. + + @property {Function} [options.onTimeout] Callback to execute after a + transaction times out. + + @property {Number} [options.pollInterval=50] Polling interval (in + milliseconds) for detecting CSS load completion in browsers that don't + support the `load` event on `` nodes. This isn't used for + JavaScript. + + @property {Number} [options.purgethreshold=20] Number of nodes to insert + before triggering an automatic purge when `autopurge` is `true`. + + @property {Number} [options.timeout] Number of milliseconds to wait before + aborting a transaction. When a timeout occurs, the `onTimeout` callback + is called, followed by `onFailure` and finally `onEnd`. By default, + there is no timeout. + + @property {String} [options.type] Resource type ("css" or "js"). This option + is set automatically by the `css()` and `js()` functions and will be + ignored there, but may be useful when using the `load()` function. If + not specified, the type will be inferred from the URL, defaulting to + "js" if the URL doesn't contain a recognizable file extension. + **/ + options: { + attributes: { + charset: 'utf-8' + }, + + purgethreshold: 20 + }, + + // -- Protected Properties ------------------------------------------------- + + /** + Regex that matches a CSS URL. Used to guess the file type when it's not + specified. + + @property REGEX_CSS + @type RegExp + @final + @protected + @static + @since 3.5.0 + **/ + REGEX_CSS: /\.css(?:[?;].*)?$/i, + + /** + Regex that matches a JS URL. Used to guess the file type when it's not + specified. + + @property REGEX_JS + @type RegExp + @final + @protected + @static + @since 3.5.0 + **/ + REGEX_JS : /\.js(?:[?;].*)?$/i, + + /** + Contains information about the current environment, such as what script and + link injection features it supports. + + This object is created and populated the first time the `_getEnv()` method + is called. + + @property _env + @type Object + @protected + @static + @since 3.5.0 + **/ + + /** + Mapping of document _yuid strings to or node references so we + don't have to look the node up each time we want to insert a request node. + + @property _insertCache + @type Object + @protected + @static + @since 3.5.0 + **/ + _insertCache: {}, + + /** + Information about the currently pending transaction, if any. + + This is actually an object with two properties: `callback`, containing the + optional callback passed to `css()`, `load()`, or `js()`; and `transaction`, + containing the actual transaction instance. + + @property _pending + @type Object + @protected + @static + @since 3.5.0 + **/ + _pending: null, + + /** + HTML nodes eligible to be purged next time autopurge is triggered. + + @property _purgeNodes + @type HTMLElement[] + @protected + @static + @since 3.5.0 + **/ + _purgeNodes: [], + + /** + Queued transactions and associated callbacks. + + @property _queue + @type Object[] + @protected + @static + @since 3.5.0 + **/ + _queue: [], + + // -- Public Methods ------------------------------------------------------- + + /** + Aborts the specified transaction. + + This will cause the transaction's `onFailure` callback to be called and + will prevent any new script and link nodes from being added to the document, + but any resources that have already been requested will continue loading + (there's no safe way to prevent this, unfortunately). + + *Note:* This method is deprecated as of 3.5.0, and will be removed in a + future version of YUI. Use the transaction-level `abort()` method instead. + + @method abort + @param {Get.Transaction} transaction Transaction to abort. + @deprecated Use the `abort()` method on the transaction instead. + @static + **/ + abort: function (transaction) { + var i, id, item, len, pending; + + + if (!transaction.abort) { + id = transaction; + pending = this._pending; + transaction = null; + + if (pending && pending.transaction.id === id) { + transaction = pending.transaction; + this._pending = null; + } else { + for (i = 0, len = this._queue.length; i < len; ++i) { + item = this._queue[i].transaction; + + if (item.id === id) { + transaction = item; + this._queue.splice(i, 1); + break; + } + } + } + } + + transaction && transaction.abort(); + }, + + /** + Loads one or more CSS files. + + The _urls_ parameter may be provided as a URL string, a request object, + or an array of URL strings and/or request objects. + + A request object is just an object that contains a `url` property and zero + or more options that should apply specifically to that request. + Request-specific options take priority over transaction-level options and + default options. + + URLs may be relative or absolute, and do not have to have the same origin + as the current page. + + The `options` parameter may be omitted completely and a callback passed in + its place, if desired. + + @example + + // Load a single CSS file and log a message on completion. + Y.Get.css('foo.css', function (err) { + if (err) { + } else { + } + }); + + // Load multiple CSS files and log a message when all have finished + // loading. + var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css']; + + Y.Get.css(urls, function (err) { + if (err) { + } else { + } + }); + + // Specify transaction-level options, which will apply to all requests + // within the transaction. + Y.Get.css(urls, { + attributes: {'class': 'my-css'}, + timeout : 5000 + }); + + // Specify per-request options, which override transaction-level and + // default options. + Y.Get.css([ + {url: 'foo.css', attributes: {id: 'foo'}}, + {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}} + ]); + + @method css + @param {String|Object|Array} urls URL string, request object, or array + of URLs and/or request objects to load. + @param {Object} [options] Options for this transaction. See the + `Y.Get.options` property for a complete list of available options. + @param {Function} [callback] Callback function to be called on completion. + This is a general callback and will be called before any more granular + callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` + object. + + @param {Array|null} callback.err Array of errors that occurred during + the transaction, or `null` on success. + @param {Get.Transaction} callback.transaction Transaction object. + + @return {Get.Transaction} Transaction object. + @static + **/ + css: function (urls, options, callback) { + return this._load('css', urls, options, callback); + }, + + /** + Loads one or more JavaScript resources. + + The _urls_ parameter may be provided as a URL string, a request object, + or an array of URL strings and/or request objects. + + A request object is just an object that contains a `url` property and zero + or more options that should apply specifically to that request. + Request-specific options take priority over transaction-level options and + default options. + + URLs may be relative or absolute, and do not have to have the same origin + as the current page. + + The `options` parameter may be omitted completely and a callback passed in + its place, if desired. + + Scripts will be executed in the order they're specified unless the `async` + option is `true`, in which case they'll be loaded in parallel and executed + in whatever order they finish loading. + + @example + + // Load a single JS file and log a message on completion. + Y.Get.js('foo.js', function (err) { + if (err) { + } else { + } + }); + + // Load multiple JS files, execute them in order, and log a message when + // all have finished loading. + var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js']; + + Y.Get.js(urls, function (err) { + if (err) { + } else { + } + }); + + // Specify transaction-level options, which will apply to all requests + // within the transaction. + Y.Get.js(urls, { + attributes: {'class': 'my-js'}, + timeout : 5000 + }); + + // Specify per-request options, which override transaction-level and + // default options. + Y.Get.js([ + {url: 'foo.js', attributes: {id: 'foo'}}, + {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}} + ]); + + @method js + @param {String|Object|Array} urls URL string, request object, or array + of URLs and/or request objects to load. + @param {Object} [options] Options for this transaction. See the + `Y.Get.options` property for a complete list of available options. + @param {Function} [callback] Callback function to be called on completion. + This is a general callback and will be called before any more granular + callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` + object. + + @param {Array|null} callback.err Array of errors that occurred during + the transaction, or `null` on success. + @param {Get.Transaction} callback.transaction Transaction object. + + @return {Get.Transaction} Transaction object. + @since 3.5.0 + @static + **/ + js: function (urls, options, callback) { + return this._load('js', urls, options, callback); + }, + + /** + Loads one or more CSS and/or JavaScript resources in the same transaction. + + Use this method when you want to load both CSS and JavaScript in a single + transaction and be notified when all requested URLs have finished loading, + regardless of type. + + Behavior and options are the same as for the `css()` and `js()` methods. If + a resource type isn't specified in per-request options or transaction-level + options, Get will guess the file type based on the URL's extension (`.css` + or `.js`, with or without a following query string). If the file type can't + be guessed from the URL, a warning will be logged and Get will assume the + URL is a JavaScript resource. + + @example + + // Load both CSS and JS files in a single transaction, and log a message + // when all files have finished loading. + Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) { + if (err) { + } else { + } + }); + + @method load + @param {String|Object|Array} urls URL string, request object, or array + of URLs and/or request objects to load. + @param {Object} [options] Options for this transaction. See the + `Y.Get.options` property for a complete list of available options. + @param {Function} [callback] Callback function to be called on completion. + This is a general callback and will be called before any more granular + callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` + object. + + @param {Array|null} err Array of errors that occurred during the + transaction, or `null` on success. + @param {Get.Transaction} Transaction object. + + @return {Get.Transaction} Transaction object. + @since 3.5.0 + @static + **/ + load: function (urls, options, callback) { + return this._load(null, urls, options, callback); + }, + + // -- Protected Methods ---------------------------------------------------- + + /** + Triggers an automatic purge if the purge threshold has been reached. + + @method _autoPurge + @param {Number} threshold Purge threshold to use, in milliseconds. + @protected + @since 3.5.0 + @static + **/ + _autoPurge: function (threshold) { + if (threshold && this._purgeNodes.length >= threshold) { + this._purge(this._purgeNodes); + } + }, + + /** + Populates the `_env` property with information about the current + environment. + + @method _getEnv + @return {Object} Environment information. + @protected + @since 3.5.0 + @static + **/ + _getEnv: function () { + var doc = Y.config.doc, + ua = Y.UA; + + // Note: some of these checks require browser sniffs since it's not + // feasible to load test files on every pageview just to perform a + // feature test. I'm sorry if this makes you sad. + return (this._env = { + + // True if this is a browser that supports disabling async mode on + // dynamically created script nodes. See + // https://developer.mozilla.org/En/HTML/Element/Script#Attributes + + // IE10 doesn't return true for the MDN feature test, so setting it explicitly, + // because it is async by default, and allows you to disable async by setting it to false + async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10), + + // True if this browser fires an event when a dynamically injected + // link node fails to load. This is currently true for Firefox 9+ + // and WebKit 535.24+ + cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0, + + // True if this browser fires an event when a dynamically injected + // link node finishes loading. This is currently true for IE, Opera, + // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the + // DOM 0 "onload" event, but not "load". All versions of IE fire + // "onload". + // davglass: Seems that Chrome on Android needs this to be false. + cssLoad: ( + (!ua.gecko && !ua.webkit) || ua.gecko >= 9 || + ua.compareVersions(ua.webkit, 535.24) >= 0 + ) && !(ua.chrome && ua.chrome <= 18), + + // True if this browser preserves script execution order while + // loading scripts in parallel as long as the script node's `async` + // attribute is set to false to explicitly disable async execution. + preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10)) + }); + }, + + _getTransaction: function (urls, options) { + var requests = [], + i, len, req, url; + + if (!Lang.isArray(urls)) { + urls = [urls]; + } + + options = Y.merge(this.options, options); + + // Clone the attributes object so we don't end up modifying it by ref. + options.attributes = Y.merge(this.options.attributes, + options.attributes); + + for (i = 0, len = urls.length; i < len; ++i) { + url = urls[i]; + req = {attributes: {}}; + + // If `url` is a string, we create a URL object for it, then mix in + // global options and request-specific options. If it's an object + // with a "url" property, we assume it's a request object containing + // URL-specific options. + if (typeof url === 'string') { + req.url = url; + } else if (url.url) { + // URL-specific options override both global defaults and + // request-specific options. + Y.mix(req, url, false, null, 0, true); + url = url.url; // Make url a string so we can use it later. + } else { + continue; + } + + Y.mix(req, options, false, null, 0, true); + + // If we didn't get an explicit type for this URL either in the + // request options or the URL-specific options, try to determine + // one from the file extension. + if (!req.type) { + if (this.REGEX_CSS.test(url)) { + req.type = 'css'; + } else { + if (!this.REGEX_JS.test(url)) { + } + + req.type = 'js'; + } + } + + // Mix in type-specific default options, but don't overwrite any + // options that have already been set. + Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions, + false, null, 0, true); + + // Give the node an id attribute if it doesn't already have one. + req.attributes.id || (req.attributes.id = Y.guid()); + + // Backcompat for <3.5.0 behavior. + if (req.win) { + req.doc = req.win.document; + } else { + req.win = req.doc.defaultView || req.doc.parentWindow; + } + + if (req.charset) { + req.attributes.charset = req.charset; + } + + requests.push(req); + } + + return new Transaction(requests, options); + }, + + _load: function (type, urls, options, callback) { + var transaction; + + // Allow callback as third param. + if (typeof options === 'function') { + callback = options; + options = {}; + } + + options || (options = {}); + options.type = type; + + options._onFinish = Get._onTransactionFinish; + + if (!this._env) { + this._getEnv(); + } + + transaction = this._getTransaction(urls, options); + + this._queue.push({ + callback : callback, + transaction: transaction + }); + + this._next(); + + return transaction; + }, + + _onTransactionFinish : function() { + Get._pending = null; + Get._next(); + }, + + _next: function () { + var item; + + if (this._pending) { + return; + } + + item = this._queue.shift(); + + if (item) { + this._pending = item; + item.transaction.execute(item.callback); + } + }, + + _purge: function (nodes) { + var purgeNodes = this._purgeNodes, + isTransaction = nodes !== purgeNodes, + index, node; + + while (node = nodes.pop()) { // assignment + // Don't purge nodes that haven't finished loading (or errored out), + // since this can hang the transaction. + if (!node._yuiget_finished) { + continue; + } + + node.parentNode && node.parentNode.removeChild(node); + + // If this is a transaction-level purge and this node also exists in + // the Get-level _purgeNodes array, we need to remove it from + // _purgeNodes to avoid creating a memory leak. The indexOf lookup + // sucks, but until we get WeakMaps, this is the least troublesome + // way to do this (we can't just hold onto node ids because they may + // not be in the same document). + if (isTransaction) { + index = Y.Array.indexOf(purgeNodes, node); + + if (index > -1) { + purgeNodes.splice(index, 1); + } + } + } + } +}; + +/** +Alias for `js()`. + +@method script +@static +**/ +Get.script = Get.js; + +/** +Represents a Get transaction, which may contain requests for one or more JS or +CSS files. + +This class should not be instantiated manually. Instances will be created and +returned as needed by Y.Get's `css()`, `js()`, and `load()` methods. + +@class Get.Transaction +@constructor +@since 3.5.0 +**/ +Get.Transaction = Transaction = function (requests, options) { + var self = this; + + self.id = Transaction._lastId += 1; + self.data = options.data; + self.errors = []; + self.nodes = []; + self.options = options; + self.requests = requests; + + self._callbacks = []; // callbacks to call after execution finishes + self._queue = []; + self._reqsWaiting = 0; + + // Deprecated pre-3.5.0 properties. + self.tId = self.id; // Use `id` instead. + self.win = options.win || Y.config.win; +}; + +/** +Arbitrary data object associated with this transaction. + +This object comes from the options passed to `Get.css()`, `Get.js()`, or +`Get.load()`, and will be `undefined` if no data object was specified. + +@property {Object} data +**/ + +/** +Array of errors that have occurred during this transaction, if any. Each error +object has the following properties: +`errors.error`: Error message. +`errors.request`: Request object related to the error. + +@since 3.5.0 +@property {Object[]} errors +**/ + +/** +Numeric id for this transaction, unique among all transactions within the same +YUI sandbox in the current pageview. + +@property {Number} id +@since 3.5.0 +**/ + +/** +HTMLElement nodes (native ones, not YUI Node instances) that have been inserted +during the current transaction. + +@property {HTMLElement[]} nodes +**/ + +/** +Options associated with this transaction. + +See `Get.options` for the full list of available options. + +@property {Object} options +@since 3.5.0 +**/ + +/** +Request objects contained in this transaction. Each request object represents +one CSS or JS URL that will be (or has been) requested and loaded into the page. + +@property {Object} requests +@since 3.5.0 +**/ + +/** +Id of the most recent transaction. + +@property _lastId +@type Number +@protected +@static +**/ +Transaction._lastId = 0; + +Transaction.prototype = { + // -- Public Properties ---------------------------------------------------- + + /** + Current state of this transaction. One of "new", "executing", or "done". + + @property _state + @type String + @protected + **/ + _state: 'new', // "new", "executing", or "done" + + // -- Public Methods ------------------------------------------------------- + + /** + Aborts this transaction. + + This will cause the transaction's `onFailure` callback to be called and + will prevent any new script and link nodes from being added to the document, + but any resources that have already been requested will continue loading + (there's no safe way to prevent this, unfortunately). + + @method abort + @param {String} [msg="Aborted."] Optional message to use in the `errors` + array describing why the transaction was aborted. + **/ + abort: function (msg) { + this._pending = null; + this._pendingCSS = null; + this._pollTimer = clearTimeout(this._pollTimer); + this._queue = []; + this._reqsWaiting = 0; + + this.errors.push({error: msg || 'Aborted'}); + this._finish(); + }, + + /** + Begins execting the transaction. + + There's usually no reason to call this manually, since Get will call it + automatically when other pending transactions have finished. If you really + want to execute your transaction before Get does, you can, but be aware that + this transaction's scripts may end up executing before the scripts in other + pending transactions. + + If the transaction is already executing, the specified callback (if any) + will be queued and called after execution finishes. If the transaction has + already finished, the callback will be called immediately (the transaction + will not be executed again). + + @method execute + @param {Function} callback Callback function to execute after all requests + in the transaction are complete, or after the transaction is aborted. + **/ + execute: function (callback) { + var self = this, + requests = self.requests, + state = self._state, + i, len, queue, req; + + if (state === 'done') { + callback && callback(self.errors.length ? self.errors : null, self); + return; + } else { + callback && self._callbacks.push(callback); + + if (state === 'executing') { + return; + } + } + + self._state = 'executing'; + self._queue = queue = []; + + if (self.options.timeout) { + self._timeout = setTimeout(function () { + self.abort('Timeout'); + }, self.options.timeout); + } + + self._reqsWaiting = requests.length; + + for (i = 0, len = requests.length; i < len; ++i) { + req = requests[i]; + + if (req.async || req.type === 'css') { + // No need to queue CSS or fully async JS. + self._insert(req); + } else { + queue.push(req); + } + } + + self._next(); + }, + + /** + Manually purges any `