diff --git a/examples/moduleLoaders/amd/index.html b/examples/moduleLoaders/amd/index.html new file mode 100644 index 0000000..a53430f --- /dev/null +++ b/examples/moduleLoaders/amd/index.html @@ -0,0 +1,13 @@ + + +
+ +type
property with any manifest item.
+ *
+ * queue.loadFile({src:"path/to/myFile.mp3x", type:AbstractLoader.SOUND});
+ *
+ * // Note that PreloadJS will not read a file extension from the query string
+ * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:AbstractLoader.IMAGE});
+ *
+ * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
+ * rawResult
property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
+ * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
+ * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
+ *
+ * var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
+ *
+ * PluginscanPlayThrough
event is fired. Browsers other
+ * than Chrome will continue to download in the background.null
when they are
+ * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true
+ * once they are complete and have been dispatched.
+ * @property _loadedScripts
+ * @type {Array}
+ * @private
+ */
+ this._loadedScripts = [];
+
+ /**
+ * The last progress amount. This is used to suppress duplicate progress events.
+ * @property _lastProgress
+ * @type {Number}
+ * @private
+ * @since 0.6.0
+ */
+ this._lastProgress = NaN;
+
+};
+
+// static properties
+/**
+ * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event is dispatched if the timeout is reached before any data is received.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000
+ * @static
+ * @since 0.4.1
+ * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
+ */
+s.loadTimeout = 8000;
+
+/**
+ * The time in milliseconds to assume a load has failed.
+ * @property LOAD_TIMEOUT
+ * @type {Number}
+ * @default 0
+ * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
+ */
+s.LOAD_TIMEOUT = 0;
+
+// Preload Types
+/**
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
+ */
+s.BINARY = AbstractLoader.BINARY;
+
+/**
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+s.CSS = AbstractLoader.CSS;
+
+/**
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+s.IMAGE = AbstractLoader.IMAGE;
+
+/**
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.JAVASCRIPT = AbstractLoader.JAVASCRIPT;
+
+/**
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
+ */
+s.JSON = AbstractLoader.JSON;
+
+/**
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
+ */
+s.JSONP = AbstractLoader.JSONP;
+
+/**
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.4.1
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
+ */
+s.MANIFEST = AbstractLoader.MANIFEST;
+
+/**
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.SOUND = AbstractLoader.SOUND;
+
+/**
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.VIDEO = AbstractLoader.VIDEO;
+
+/**
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
+ */
+s.SVG = AbstractLoader.SVG;
+
+/**
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
+ */
+s.TEXT = AbstractLoader.TEXT;
+
+/**
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
+ */
+s.XML = AbstractLoader.XML;
+
+/**
+ * @property POST
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
+ */
+s.POST = AbstractLoader.POST;
+
+/**
+ * @property GET
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
+ */
+s.GET = AbstractLoader.GET;
+
+// events
+/**
+ * This event is fired when an individual file has loaded, and been processed.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.3.0
+ */
+
+/**
+ * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
+ * @event fileprogress
+ * @since 0.3.0
+ */
+
+/**
+ * This event is fired when an individual file starts to load.
+ * @event filestart
+ * @param {Object} The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a property.
+ */
+
+/**
+ * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from
+ * a LoadQueue instance.
+ * @event initialize
+ * @private
+ */
+
+// public methods
+/**
+ * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
+ * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
+ * once, and will be prepended to the list of available loaders.
+ * @method registerLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
+ * @since 0.6.0
+ */
+p.registerLoader = function (loader) {
+ if (!loader || !loader.canLoadItem) {
+ throw new Error("loader is of an incorrect type.");
+ } else if (this._availableLoaders.indexOf(loader) != -1) {
+ throw new Error("loader already exists."); //LM: Maybe just silently fail here
+ }
+
+ this._availableLoaders.unshift(loader);
+};
+
+/**
+ * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
+ * unregistered, the default loaders will always be available.
+ * @method unregisterLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
+ */
+p.unregisterLoader = function (loader) {
+ var idx = this._availableLoaders.indexOf(loader);
+ if (idx != -1 && idx < this._defaultLoaderLength - 1) {
+ this._availableLoaders.splice(idx, 1);
+ }
+};
+
+/**
+ * @method setUseXHR
+ * @param {Boolean} value The new useXHR value to set.
+ * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
+ * the provided value argument was true.
+ * @since 0.3.0
+ * @deprecated use the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property, or the
+ * {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} method instead.
+ */
+p.setUseXHR = function (value) {
+ return this.setPreferXHR(value);
+};
+
+/**
+ * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
+ * fail, or be ignored depending on the browser's capabilities and the load type.
+ * @method setPreferXHR
+ * @param {Boolean} value
+ * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
+ * @since 0.6.0
+ */
+p.setPreferXHR = function (value) {
+ // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
+ //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
+ this.preferXHR = (value != false && window.XMLHttpRequest != null);
+ return this.preferXHR;
+};
+
+/**
+ * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
+ * content, and allows the queue to be used again.
+ * @method removeAll
+ * @since 0.3.0
+ */
+p.removeAll = function () {
+ this.remove();
+};
+
+/**
+ * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
+ * This also removes internal references to loaded item(s).
+ *
+ * Example
+ *
+ * queue.loadManifest([
+ * {src:"test.png", id:"png"},
+ * {src:"test.jpg", id:"jpg"},
+ * {src:"test.mp3", id:"mp3"}
+ * ]);
+ * queue.remove("png"); // Single item by ID
+ * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
+ * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
+ *
+ * @method remove
+ * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
+ * items, or multiple items as arguments.
+ * @since 0.3.0
+ */
+p.remove = function (idsOrUrls) {
+ var args = null;
+
+ if (idsOrUrls && !Array.isArray(idsOrUrls)) {
+ args = [idsOrUrls];
+ } else if (idsOrUrls) {
+ args = idsOrUrls;
+ } else if (arguments.length > 0) {
+ return;
+ }
+
+ var itemsWereRemoved = false;
+
+ // Destroy everything
+ if (!args) {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
+ this.init(this.preferXHR, this._basePath);
+
+ // Remove specific items
+ } else {
+ while (args.length) {
+ var item = args.pop();
+ var r = this.getResult(item);
+
+ //Remove from the main load Queue
+ for (i = this._loadQueue.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueue[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueue.splice(i, 1)[0].cancel();
+ break;
+ }
+ }
+
+ //Remove from the backup queue
+ for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueueBackup[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueueBackup.splice(i, 1)[0].cancel();
+ break;
+ }
+ }
+
+ if (r) {
+ this._disposeItem(this.getItem(item));
+ } else {
+ for (var i = this._currentLoads.length - 1; i >= 0; i--) {
+ var loadItem = this._currentLoads[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._currentLoads.splice(i, 1)[0].cancel();
+ itemsWereRemoved = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // If this was called during a load, try to load the next item.
+ if (itemsWereRemoved) {
+ this._loadNext();
+ }
+ }
+};
+
+/**
+ * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
+ * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
+ * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
+ * @method reset
+ * @since 0.3.0
+ */
+p.reset = function () {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
+
+ //Reset the queue to its start state
+ var a = [];
+ for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
+ a.push(this._loadQueueBackup[i].getItem());
+ }
+
+ this.loadManifest(a, false);
+};
+
+/**
+ * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
+ * Currently, only one plugin can exist per type/extension.
+ *
+ * When a plugin is installed, a getPreloadHandlers()
method will be called on it. For more information
+ * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
+ * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
+ *
+ * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
+ * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
+ * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
+ * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
+ * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
+ * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
+ *
+ * @method installPlugin
+ * @param {Function} plugin The plugin class to install.
+ */
+p.installPlugin = function (plugin) {
+ if (plugin == null) {
+ return;
+ }
+
+ if (plugin.getPreloadHandlers != null) {
+ this._plugins.push(plugin);
+ var map = plugin.getPreloadHandlers();
+ map.scope = plugin;
+
+ if (map.types != null) {
+ for (var i = 0, l = map.types.length; i < l; i++) {
+ this._typeCallbacks[map.types[i]] = map;
+ }
+ }
+
+ if (map.extensions != null) {
+ for (i = 0, l = map.extensions.length; i < l; i++) {
+ this._extensionCallbacks[map.extensions[i]] = map;
+ }
+ }
+ }
+};
+
+/**
+ * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
+ * number of open connections, so any additional connections may remain in a pending state until the browser
+ * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
+ * is `true`, only one script is loaded at a time due to browser limitations.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(10); // Allow 10 concurrent loads
+ *
+ * @method setMaxConnections
+ * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
+ * is open at any time.
+ */
+p.setMaxConnections = function (value) {
+ this._maxConnections = value;
+ if (!this._paused && this._loadQueue.length > 0) {
+ this._loadNext();
+ }
+};
+
+/**
+ * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method.
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadFile
+ * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+p.loadFile = function (file, loadNow, basePath) {
+ if (file == null) {
+ var event = new ErrorEvent("PRELOAD_NO_FILE");
+ this._sendError(event);
+ return;
+ }
+ this._addItem(file, null, basePath);
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+};
+
+/**
+ * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
+ * The files in the manifest are requested in the same order, but may complete in a different order if the max
+ * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
+ * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
+ * default).
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadManifest
+ * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
+ * manifests:
+ *
+ * - A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
+ * which defines the list of files to load, and can optionally contain a "path" property, which will be
+ * prepended to each file in the list.
+ * - An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
+ * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
+ * and can optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An object which contains a "manifest" property, which defines the list of files to load, and can
+ * optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An Array of files to load.
+ *
+ *
+ * Each "file" in a manifest can be either:
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+p.loadManifest = function (manifest, loadNow, basePath) {
+ var fileList = null;
+ var path = null;
+
+ // Array-based list of items
+ if (Array.isArray(manifest)) {
+ if (manifest.length == 0) {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_EMPTY");
+ this._sendError(event);
+ return;
+ }
+ fileList = manifest;
+
+ // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
+ } else if (typeof(manifest) === "string") {
+ fileList = [
+ {
+ src: manifest,
+ type: s.MANIFEST
+ }
+ ];
+
+ } else if (typeof(manifest) == "object") {
+
+ // An object that defines a manifest path
+ if (manifest.src !== undefined) {
+ if (manifest.type == null) {
+ manifest.type = s.MANIFEST;
+ } else if (manifest.type != s.MANIFEST) {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_TYPE");
+ this._sendError(event);
+ }
+ fileList = [manifest];
+
+ // An object that defines a manifest
+ } else if (manifest.manifest !== undefined) {
+ fileList = manifest.manifest;
+ path = manifest.path;
+ }
+
+ // Unsupported. This will throw an error.
+ } else {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_NULL");
+ this._sendError(event);
+ return;
+ }
+
+ for (var i = 0, l = fileList.length; i < l; i++) {
+ this._addItem(fileList[i], path, basePath);
+ }
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+
+};
+
+/**
+ * Start a LoadQueue that was created, but not automatically started.
+ * @method load
+ */
+p.load = function () {
+ this.setPaused(false);
+};
+
+/**
+ * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
+ * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getItem
+ * @param {String} value The id
or src
of the load item.
+ * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event as the `item` parameter.
+ */
+p.getItem = function (value) {
+ return this._loadItemsById[value] || this._loadItemsBySrc[value];
+};
+
+/**
+ * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
+ * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getResult
+ * @param {String} value The id
or src
of the load item.
+ * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML
+ * DOM.
+ * - A style tag for CSS (<style /> or <link >)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - A binary arraybuffer loaded by XHR
+ * - An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play
+ * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
+ * which can not be used to play audio back.
+ *
+ * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
+ * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+p.getResult = function (value, rawResult) {
+ var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
+ if (item == null) {
+ return null;
+ }
+ var id = item.id;
+ if (rawResult && this._loadedRawResults[id]) {
+ return this._loadedRawResults[id];
+ }
+ return this._loadedResults[id];
+};
+
+/**
+ * Generate an list of items loaded by this queue.
+ * @method getItems
+ * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
+ * and failed load items will also be included.
+ * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
+ * result, and rawResult.
+ * @since 0.6.0
+ */
+p.getItems = function (loaded) {
+ var arr = [];
+ for (var n in this._loadItemsById) {
+ var item = this._loadItemsById[n];
+ var result = this.getResult(n);
+ if (loaded === true && result == null) {
+ continue;
+ }
+ arr.push({
+ item: item,
+ result: result,
+ rawResult: this.getResult(n, true)
+ });
+ }
+ return arr;
+};
+
+/**
+ * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
+ * be processed when active loads complete. LoadQueues are not paused by default.
+ *
+ * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
+ * argument is `false`.
+ * @method setPaused
+ * @param {Boolean} value Whether the queue should be paused or not.
+ */
+p.setPaused = function (value) {
+ this._paused = value;
+ if (!this._paused) {
+ this._loadNext();
+ }
+};
+
+/**
+ * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
+ * starting to download. Note that currently any active loads will remain open, and events may be processed.
+ *
+ * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
+ * @method close
+ */
+p.close = function () {
+ while (this._currentLoads.length) {
+ this._currentLoads.pop().cancel();
+ }
+ this._scriptOrder.length = 0;
+ this._loadedScripts.length = 0;
+ this.loadStartWasDispatched = false;
+ this._itemCount = 0;
+ this._lastProgress = NaN;
+};
+
+// protected methods
+/**
+ * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
+ * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
+ * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
+ * method.
+ * @method _addItem
+ * @param {String|Object} value The item to add to the queue.
+ * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
+ * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
+ * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
+ * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
+ * version.
+ * @private
+ */
+p._addItem = function (value, path, basePath) {
+ var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
+ if (item == null) {
+ return;
+ } // Sometimes plugins or types should be skipped.
+ var loader = this._createLoader(item);
+ if (loader != null) {
+ if ("plugins" in loader) {
+ loader.plugins = this._plugins;
+ }
+ item._loader = loader;
+ this._loadQueue.push(loader);
+ this._loadQueueBackup.push(loader);
+
+ this._numItems++;
+ this._updateProgress();
+
+ // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
+ if ((this.maintainScriptOrder
+ && item.type == LoadQueue.JAVASCRIPT
+ //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
+ )
+ || item.maintainOrder === true) {
+ this._scriptOrder.push(item);
+ this._loadedScripts.push(null);
+ }
+ }
+};
+
+/**
+ * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
+ * item is determined by browser support, requirements based on the file type, and developer settings. For example,
+ * XHR is only used for file types that support it in new browsers.
+ *
+ * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
+ * alter the load item.
+ * @method _createLoadItem
+ * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
+ * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
+ * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
+ * when it is added.
+ * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to
+ * the path argument.
+ * @return {Object} The loader instance that will be used.
+ * @private
+ */
+p._createLoadItem = function (value, path, basePath) {
+ var item = LoadItem.create(value);
+ if (item == null) {
+ return null;
+ }
+
+ var bp = ""; // Store the generated basePath
+ var useBasePath = basePath || this._basePath;
+
+ if (item.src instanceof Object) {
+ if (!item.type) {
+ return null;
+ } // the the src is an object, type is required to pass off to plugin
+ if (path) {
+ bp = path;
+ var pathMatch = RequestUtils.parseURI(path);
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ } else {
+ // Determine Extension, etc.
+ var match = RequestUtils.parseURI(item.src);
+ if (match.extension) {
+ item.ext = match.extension;
+ }
+ if (item.type == null) {
+ item.type = RequestUtils.getTypeByExtension(item.ext);
+ }
+
+ // Inject path & basePath
+ var autoId = item.src;
+ if (!match.absolute && !match.relative) {
+ if (path) {
+ bp = path;
+ var pathMatch = RequestUtils.parseURI(path);
+ autoId = path + autoId;
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ }
+ item.src = bp + item.src;
+ }
+ item.path = bp;
+
+ // If there's no id, set one now.
+ if (item.id === undefined || item.id === null || item.id === "") {
+ item.id = autoId;
+ }
+
+ // Give plugins a chance to modify the loadItem:
+ var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
+ if (customHandler) {
+ // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
+ var result = customHandler.callback.call(customHandler.scope, item, this);
+
+ // The plugin will handle the load, or has canceled it. Ignore it.
+ if (result === false) {
+ return null;
+
+ // Load as normal:
+ } else if (result === true) {
+ // Do Nothing
+
+ // Result is a loader class:
+ } else if (result != null) {
+ item._loader = result;
+ }
+
+ // Update the extension in case the type changed:
+ match = RequestUtils.parseURI(item.src);
+ if (match.extension != null) {
+ item.ext = match.extension;
+ }
+ }
+
+ // Store the item for lookup. This also helps clean-up later.
+ this._loadItemsById[item.id] = item;
+ this._loadItemsBySrc[item.src] = item;
+
+ if (item.crossOrigin == null) {
+ item.crossOrigin = this._crossOrigin;
+ }
+
+ return item;
+};
+
+/**
+ * Create a loader for a load item.
+ * @method _createLoader
+ * @param {Object} item A formatted load item that can be used to generate a loader.
+ * @return {AbstractLoader} A loader that can be used to load content.
+ * @private
+ */
+p._createLoader = function (item) {
+ if (item._loader != null) { // A plugin already specified a loader
+ return item._loader;
+ }
+
+ // Initially, try and use the provided/supported XHR mode:
+ var preferXHR = this.preferXHR;
+
+ for (var i = 0; i < this._availableLoaders.length; i++) {
+ var loader = this._availableLoaders[i];
+ if (loader && loader.canLoadItem(item)) {
+ return new loader(item, preferXHR);
+ }
+ }
+
+ // TODO: Log error (requires createjs.log)
+ return null;
+};
+
+/**
+ * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
+ * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
+ * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
+ * using tags, which have to be loaded one at a time to maintain load order.
+ * @method _loadNext
+ * @private
+ */
+p._loadNext = function () {
+ if (this._paused) {
+ return;
+ }
+
+ // Only dispatch loadstart event when the first file is loaded.
+ if (!this._loadStartWasDispatched) {
+ this._sendLoadStart();
+ this._loadStartWasDispatched = true;
+ }
+
+ // The queue has completed.
+ if (this._numItems == this._numItemsLoaded) {
+ this.loaded = true;
+ this._sendComplete();
+
+ // Load the next queue, if it has been defined.
+ if (this.next && this.next.load) {
+ this.next.load();
+ }
+ } else {
+ this.loaded = false;
+ }
+
+ // Must iterate forwards to load in the right order.
+ for (var i = 0; i < this._loadQueue.length; i++) {
+ if (this._currentLoads.length >= this._maxConnections) {
+ break;
+ }
+ var loader = this._loadQueue[i];
+
+ // Determine if we should be only loading one tag-script at a time:
+ // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
+ if (!this._canStartLoad(loader)) {
+ continue;
+ }
+ this._loadQueue.splice(i, 1);
+ i--;
+ this._loadItem(loader);
+ }
+};
+
+/**
+ * Begin loading an item. Event listeners are not added to the loaders until the load starts.
+ * @method _loadItem
+ * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
+ * @private
+ */
+p._loadItem = function (loader) {
+ loader.on("fileload", this._handleFileLoad, this);
+ loader.on("progress", this._handleProgress, this);
+ loader.on("complete", this._handleFileComplete, this);
+ loader.on("error", this._handleError, this);
+ loader.on("fileerror", this._handleFileError, this);
+ this._currentLoads.push(loader);
+ this._sendFileStart(loader.getItem());
+ loader.load();
+};
+
+/**
+ * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
+ * events.
+ * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
+ * @private
+ * @since 0.6.0
+ */
+p._handleFileLoad = function (event) {
+ event.target = null;
+ this.dispatchEvent(event);
+};
+
+/**
+ * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
+ * loaders like M
+ * @param event
+ * @private
+ */
+p._handleFileError = function (event) {
+ var newEvent = new ErrorEvent("FILE_LOAD_ERROR", null, event.item);
+ this._sendError(newEvent);
+};
+
+/**
+ * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
+ * is set to `true`.
+ * @method _handleError
+ * @param {ErrorEvent} event The error event, containing relevant error information.
+ * @private
+ */
+p._handleError = function (event) {
+ var loader = event.target;
+ this._numItemsLoaded++;
+
+ this._finishOrderedItem(loader, true);
+ this._updateProgress();
+
+ var newEvent = new ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
+ // TODO: Propagate actual error message.
+
+ this._sendError(newEvent);
+
+ if (!this.stopOnError) {
+ this._removeLoadItem(loader);
+ this._cleanLoadItem(loader);
+ this._loadNext();
+ } else {
+ this.setPaused(true);
+ }
+};
+
+/**
+ * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
+ * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
+ * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
+ * @method _handleFileComplete
+ * @param {Event} event The event object from the loader.
+ * @private
+ */
+p._handleFileComplete = function (event) {
+ var loader = event.target;
+ var item = loader.getItem();
+
+ var result = loader.getResult();
+ this._loadedResults[item.id] = result;
+ var rawResult = loader.getResult(true);
+ if (rawResult != null && rawResult !== result) {
+ this._loadedRawResults[item.id] = rawResult;
+ }
+
+ this._saveLoadedItems(loader);
+
+ // Remove the load item
+ this._removeLoadItem(loader);
+
+ if (!this._finishOrderedItem(loader)) {
+ // The item was NOT managed, so process it now
+ this._processFinishedLoad(item, loader);
+ }
+
+ // Clean up the load item
+ this._cleanLoadItem(loader);
+};
+
+/**
+ * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
+ * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
+ * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
+ * methods.
+ * @method _saveLoadedItems
+ * @param {AbstractLoader} loader
+ * @protected
+ * @since 0.6.0
+ */
+p._saveLoadedItems = function (loader) {
+ // TODO: Not sure how to handle this. Would be nice to expose the items.
+ // Loaders may load sub-items. This adds them to this queue
+ var list = loader.getLoadedItems();
+ if (list === null) {
+ return;
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i].item;
+
+ // Store item lookups
+ this._loadItemsBySrc[item.src] = item;
+ this._loadItemsById[item.id] = item;
+
+ // Store loaded content
+ this._loadedResults[item.id] = list[i].result;
+ this._loadedRawResults[item.id] = list[i].rawResult;
+ }
+};
+
+/**
+ * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
+ * so, trigger prior items to trigger as well.
+ * @method _finishOrderedItem
+ * @param {AbstractLoader} loader
+ * @param {Boolean} loadFailed
+ * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
+ * behaviour if it is.
+ * @private
+ */
+p._finishOrderedItem = function (loader, loadFailed) {
+ var item = loader.getItem();
+
+ if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
+ || item.maintainOrder) {
+
+ //TODO: Evaluate removal of the _currentlyLoadingScript
+ if (loader instanceof createjs.JavaScriptLoader) {
+ this._currentlyLoadingScript = false;
+ }
+
+ var index = createjs.indexOf(this._scriptOrder, item);
+ if (index == -1) {
+ return false;
+ } // This loader no longer exists
+ this._loadedScripts[index] = (loadFailed === true) ? true : item;
+
+ this._checkScriptLoadOrder();
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
+ * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
+ * and then when they are processed and dispatched, the value is set to `true`. This method simply
+ * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
+ * dispatched.
+ * @method _checkScriptLoadOrder
+ * @private
+ */
+p._checkScriptLoadOrder = function () {
+ var l = this._loadedScripts.length;
+
+ for (var i = 0; i < l; i++) {
+ var item = this._loadedScripts[i];
+ if (item === null) {
+ break;
+ } // This is still loading. Do not process further.
+ if (item === true) {
+ continue;
+ } // This has completed, and been processed. Move on.
+
+ var loadItem = this._loadedResults[item.id];
+ if (item.type == createjs.LoadQueue.JAVASCRIPT) {
+ // Append script tags to the head automatically.
+ createjs.DomUtils.appendToHead(loadItem);
+ }
+
+ var loader = item._loader;
+ this._processFinishedLoad(item, loader);
+ this._loadedScripts[i] = true;
+ }
+};
+
+/**
+ * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
+ * the next item.
+ * @method _processFinishedLoad
+ * @param {LoadItem|Object} item
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+p._processFinishedLoad = function (item, loader) {
+ this._numItemsLoaded++;
+
+ // Since LoadQueue needs maintain order, we can't append scripts in the loader.
+ // So we do it here instead. Or in _checkScriptLoadOrder();
+ if (!this.maintainScriptOrder && item.type == LoadQueue.JAVASCRIPT) {
+ var tag = loader.getTag();
+ createjs.DomUtils.appendToHead(tag);
+ }
+
+ this._updateProgress();
+ this._sendFileComplete(item, loader);
+ this._loadNext();
+};
+
+/**
+ * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
+ * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before
+ * the script can even be started, since it exist in the DOM while loading.
+ * @method _canStartLoad
+ * @param {AbstractLoader} loader The loader for the item
+ * @return {Boolean} Whether the item can start a load or not.
+ * @private
+ */
+p._canStartLoad = function (loader) {
+ if (!this.maintainScriptOrder || loader.preferXHR) {
+ return true;
+ }
+ var item = loader.getItem();
+ if (item.type != LoadQueue.JAVASCRIPT) {
+ return true;
+ }
+ if (this._currentlyLoadingScript) {
+ return false;
+ }
+
+ var index = this._scriptOrder.indexOf(item);
+ var i = 0;
+ while (i < index) {
+ var checkItem = this._loadedScripts[i];
+ if (checkItem == null) {
+ return false;
+ }
+ i++;
+ }
+ this._currentlyLoadingScript = true;
+ return true;
+};
+
+/**
+ * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
+ * @method _removeLoadItem
+ * @param {AbstractLoader} loader A loader instance to remove.
+ * @private
+ */
+p._removeLoadItem = function (loader) {
+ var l = this._currentLoads.length;
+ for (var i = 0; i < l; i++) {
+ if (this._currentLoads[i] == loader) {
+ this._currentLoads.splice(i, 1);
+ break;
+ }
+ }
+};
+
+/**
+ * Remove unneeded references from a loader.
+ *
+ * @param loader
+ * @private
+ */
+p._cleanLoadItem = function (loader) {
+ var item = loader.getItem();
+ if (item) {
+ delete item._loader;
+ }
+}
+
+/**
+ * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
+ * @method _handleProgress
+ * @param {ProgressEvent} event The progress event from the item.
+ * @private
+ */
+p._handleProgress = function (event) {
+ var loader = event.target;
+ this._sendFileProgress(loader.getItem(), loader.progress);
+ this._updateProgress();
+};
+
+/**
+ * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
+ * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
+ * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
+ * loaded progress on top of the already-loaded items.
+ *
+ * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
+ *
+ * - 5/10 of the items in the queue (50%)
+ * - plus 20% of item 6's slot (2%)
+ * - equals 52%
+ *
+ * @method _updateProgress
+ * @private
+ */
+p._updateProgress = function () {
+ var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
+ var remaining = this._numItems - this._numItemsLoaded;
+ if (remaining > 0) {
+ var chunk = 0;
+ for (var i = 0, l = this._currentLoads.length; i < l; i++) {
+ chunk += this._currentLoads[i].progress;
+ }
+ loaded += (chunk / remaining) * (remaining / this._numItems);
+ }
+
+ if (this._lastProgress != loaded) {
+ this._sendProgress(loaded);
+ this._lastProgress = loaded;
+ }
+};
+
+/**
+ * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
+ * hashes.
+ * @method _disposeItem
+ * @param {LoadItem|Object} item The item that was passed in for preloading.
+ * @private
+ */
+p._disposeItem = function (item) {
+ delete this._loadedResults[item.id];
+ delete this._loadedRawResults[item.id];
+ delete this._loadItemsById[item.id];
+ delete this._loadItemsBySrc[item.src];
+};
+
+/**
+ * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendFileProgress
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @param {Number} progress The amount the item has been loaded (between 0 and 1).
+ * @protected
+ */
+p._sendFileProgress = function (item, progress) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+ if (!this.hasEventListener("fileprogress")) {
+ return;
+ }
+
+ //LM: Rework ProgressEvent to support this?
+ var event = new Event("fileprogress");
+ event.progress = progress;
+ event.loaded = progress;
+ event.total = 1;
+ event.item = item;
+
+ this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
+ * details on the event payload.
+ * @method _sendFileComplete
+ * @param {LoadItemObject} item The item that is being loaded.
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+p._sendFileComplete = function (item, loader) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+
+ var event = new Event("fileload");
+ event.loader = loader;
+ event.item = item;
+ event.result = this._loadedResults[item.id];
+ event.rawResult = this._loadedRawResults[item.id];
+
+ // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
+ if (item.completeHandler) {
+ item.completeHandler(event);
+ }
+
+ this.hasEventListener("fileload") && this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
+ * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
+ * @method _sendFileStart
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @protected
+ */
+p._sendFileStart = function (item) {
+ var event = new Event("filestart");
+ event.item = item;
+ this.hasEventListener("filestart") && this.dispatchEvent(event);
+};
+
+p.toString = function () {
+ return "[PreloadJS LoadQueue]";
+};
+
+var LoadQueue = promote(LoadQueue, "AbstractLoader");
+
+module.exports = LoadQueue;
+},{"../createjs/events/ErrorEvent":1,"../createjs/events/Event":2,"../createjs/utils/extend":4,"../createjs/utils/promote":5,"./data/LoadItem":8,"./loaders/AbstractLoader":10,"./loaders/ImageLoader":11,"./utils/RequestUtils":15}],8:[function(_dereq_,module,exports){
+/*
+ * LoadItem
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+// namespace:
+
+/**
+ * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead,
+ * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A
+ * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the
+ * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}}
+ * @class LoadItem
+ * @constructor
+ * @since 0.6.0
+ */
+function LoadItem() {
+ /**
+ * The source of the file that is being loaded. This property is required. The source can either be a
+ * string (recommended), or an HTML tag.
+ * This can also be an object, but in that case it has to include a type and be handled by a plugin.
+ * @property src
+ * @type {String}
+ * @default null
+ */
+ this.src = null;
+
+ /**
+ * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
+ * be set manually. This is helpful in cases where a file does not have an extension.
+ * @property type
+ * @type {String}
+ * @default null
+ */
+ this.type = null;
+
+ /**
+ * A string identifier which can be used to reference the loaded object. If none is provided, this will be
+ * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
+ * @property id
+ * @type {String}
+ * @default null
+ */
+ this.id = null;
+
+ /**
+ * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
+ * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
+ * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
+ * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
+ * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
+ * @property maintainOrder
+ * @type {Boolean}
+ * @default false
+ */
+ this.maintainOrder = false;
+
+ /**
+ * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
+ * @property callback
+ * @type {String}
+ * @default null
+ */
+ this.callback = null;
+
+ /**
+ * An arbitrary data object, which is included with the loaded object.
+ * @property data
+ * @type {Object}
+ * @default null
+ */
+ this.data = null;
+
+ /**
+ * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
+ * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
+ * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @property method
+ * @type {String}
+ * @default get
+ */
+ this.method = LoadItem.GET;
+
+ /**
+ * An object hash of name/value pairs to send to the server.
+ * @property values
+ * @type {Object}
+ * @default null
+ */
+ this.values = null;
+
+ /**
+ * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
+ * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
+ * default headers by including them in your headers object.
+ * @property headers
+ * @type {Object}
+ * @default null
+ */
+ this.headers = null;
+
+ /**
+ * Enable credentials for XHR requests.
+ * @property withCredentials
+ * @type {Boolean}
+ * @default false
+ */
+ this.withCredentials = false;
+
+ /**
+ * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
+ * based files (json, xml, text, css, js).
+ * @property mimeType
+ * @type {String}
+ * @default null
+ */
+ this.mimeType = null;
+
+ /**
+ * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
+ * @property crossOrigin
+ * @type {boolean}
+ * @default Anonymous
+ */
+ this.crossOrigin = null;
+
+ /**
+ * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000 (8 seconds)
+ */
+ this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+};
+
+var p = LoadItem.prototype = {};
+var s = LoadItem;
+
+/**
+ * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property LOAD_TIMEOUT_DEFAULT
+ * @type {number}
+ * @static
+ */
+s.LOAD_TIMEOUT_DEFAULT = 8000;
+
+/**
+ * Create a LoadItem.
+ *
+ * - String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
+ * - LoadItem instances are returned as-is
+ * - Objects are returned with any needed properties added
+ *
+ * @method create
+ * @param {LoadItem|String|Object} value The load item value
+ * @returns {LoadItem|Object}
+ * @static
+ */
+s.create = function (value) {
+ if (typeof value == "string") {
+ var item = new LoadItem();
+ item.src = value;
+ return item;
+ } else if (value instanceof s) {
+ return value;
+ } else if (value instanceof Object && value.src) {
+ if (value.loadTimeout == null) {
+ value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+ }
+ return value;
+ } else {
+ throw new Error("Type not recognized.");
+ }
+};
+
+/**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * Example
+ *
+ * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
+ * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
+ */
+p.set = function (props) {
+ for (var n in props) {
+ this[n] = props[n];
+ }
+ return this;
+};
+
+var LoadItem = s;
+module.exports = LoadItem;
+
+},{}],9:[function(_dereq_,module,exports){
+/*
+ * ProgressEvent
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var promote = _dereq_('../../createjs/utils/promote');
+var extend = _dereq_('../../createjs/utils/extend');
+var Event = _dereq_('../../createjs/events/Event');
+
+// constructor
+/**
+ * A CreateJS {{#crossLink "Event"}}{{/crossLink}} that is dispatched when progress changes.
+ * @class ProgressEvent
+ * @param {Number} loaded The amount that has been loaded. This can be any number relative to the total.
+ * @param {Number} [total=1] The total amount that will load. This will default to 1, so if the `loaded` value is
+ * a percentage (between 0 and 1), it can be omitted.
+ * @todo Consider having this event be a "fileprogress" event as well
+ * @constructor
+ */
+function ProgressEvent(loaded, total) {
+ this.Event_constructor("progress");
+
+ /**
+ * The amount that has been loaded (out of a total amount)
+ * @property loaded
+ * @type {Number}
+ */
+ this.loaded = loaded;
+
+ /**
+ * The total "size" of the load.
+ * @property total
+ * @type {Number}
+ * @default 1
+ */
+ this.total = (total == null) ? 1 : total;
+
+ /**
+ * The percentage (out of 1) that the load has been completed. This is calculated using `loaded/total`.
+ * @property progress
+ * @type {Number}
+ * @default 0
+ */
+ this.progress = (total == 0) ? 0 : this.loaded / this.total;
+};
+
+var p = extend(ProgressEvent, Event);
+
+/**
+ * Returns a clone of the ProgressEvent instance.
+ * @method clone
+ * @return {ProgressEvent} a clone of the Event instance.
+ **/
+p.clone = function () {
+ return new ProgressEvent(this.loaded, this.total);
+};
+
+var ProgressEvent = promote(ProgressEvent, "Event");
+module.exports = ProgressEvent;
+
+},{"../../createjs/events/Event":2,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5}],10:[function(_dereq_,module,exports){
+/*
+ * AbstractLoader
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var EventDispatcher = _dereq_('../../createjs/events/EventDispatcher');
+var LoadItem = _dereq_('../data/LoadItem');
+var Event = _dereq_('../../createjs/events/Event');
+var ErrorEvent = _dereq_('../../createjs/events/ErrorEvent');
+var ProgressEvent = _dereq_('../events/ProgressEvent');
+var RequestUtils = _dereq_('../utils/RequestUtils');
+var TagRequest = _dereq_('../net/TagRequest');
+var XHRRequest = _dereq_('../net/XHRRequest');
+var proxy = _dereq_('../../createjs/utils/proxy');
+var promote = _dereq_('../../createjs/utils/promote');
+var extend = _dereq_('../../createjs/utils/extend');
+
+// namespace:
+// constructor
+/**
+ * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
+ * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
+ * @class AbstractLoader
+ * @param {LoadItem|object|string} loadItem The item to be loaded.
+ * @param {Boolean} [preferXHR] Determines if the LoadItem should try and load using XHR, or take a
+ * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
+ * other, so this is a suggested directive.
+ * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
+ * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
+ * @extends EventDispatcher
+ */
+function AbstractLoader(loadItem, preferXHR, type) {
+ this.EventDispatcher_constructor();
+
+ // public properties
+ /**
+ * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
+ * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
+ * @property loaded
+ * @type {Boolean}
+ * @default false
+ */
+ this.loaded = false;
+
+ /**
+ * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
+ * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
+ * instead.
+ * @property canceled
+ * @type {Boolean}
+ * @default false
+ * @readonly
+ */
+ this.canceled = false;
+
+ /**
+ * The current load progress (percentage) for this item. This will be a number between 0 and 1.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.loadFile("largeImage.png");
+ * queue.on("progress", function() {
+ * console.log("Progress:", queue.progress, event.progress);
+ * });
+ *
+ * @property progress
+ * @type {Number}
+ * @default 0
+ */
+ this.progress = 0;
+
+ /**
+ * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
+ * supported types.
+ * @property type
+ * @type {String}
+ */
+ this.type = type;
+
+ /**
+ * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
+ * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
+ * can be overridden to provide custom formatting.
+ *
+ * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
+ * asynchronous, such as creating a new image. The callback function is passed 2 parameters, which are callbacks
+ * to handle success and error conditions in the resultFormatter. Note that the resultFormatter method is
+ * called in the current scope, as well as the success and error callbacks.
+ *
+ * Example asynchronous resultFormatter
+ *
+ * function _formatResult(loader) {
+ * return function(success, error) {
+ * if (errorCondition) { error(errorDetailEvent); }
+ * success(result);
+ * }
+ * }
+ * @property resultFormatter
+ * @type {Function}
+ * @default null
+ */
+ this.resultFormatter = null;
+
+ // protected properties
+ /**
+ * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
+ * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
+ * @property _item
+ * @type {LoadItem|Object}
+ * @private
+ */
+ if (loadItem) {
+ this._item = LoadItem.create(loadItem);
+ } else {
+ this._item = null;
+ }
+
+ /**
+ * Whether the loader will try and load content using XHR (true) or HTML tags (false).
+ * @property _preferXHR
+ * @type {Boolean}
+ * @private
+ */
+ this._preferXHR = preferXHR;
+
+ /**
+ * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
+ * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
+ * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
+ * @property _result
+ * @type {Object|String}
+ * @private
+ */
+ this._result = null;
+
+ /**
+ * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
+ * method, and passing `true`.
+ * @property _rawResult
+ * @type {Object|String}
+ * @private
+ */
+ this._rawResult = null;
+
+ /**
+ * A list of items that loaders load behind the scenes. This does not include the main item the loader is
+ * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _loadItems
+ * @type {null}
+ * @protected
+ */
+ this._loadedItems = null;
+
+ /**
+ * The attribute the items loaded using tags use for the source.
+ * @type {string}
+ * @default null
+ * @private
+ */
+ this._tagSrcAttribute = null;
+
+ /**
+ * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
+ * @property _tag
+ * @type {Object}
+ * @private
+ */
+ this._tag = null;
+};
+
+var p = extend(AbstractLoader, EventDispatcher);
+var s = AbstractLoader;
+
+// TODO: deprecated
+// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
+
+
+/**
+ * Defines a POST request, use for a method value when loading data.
+ * @property POST
+ * @type {string}
+ * @default post
+ * @static
+ */
+s.POST = "POST";
+
+/**
+ * Defines a GET request, use for a method value when loading data.
+ * @property GET
+ * @type {string}
+ * @default get
+ * @static
+ */
+s.GET = "GET";
+
+/**
+ * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @since 0.6.0
+ */
+s.BINARY = "binary";
+
+/**
+ * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a
+ * <style> tag when loaded with tags.
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @since 0.6.0
+ */
+s.CSS = "css";
+
+/**
+ * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag.
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @since 0.6.0
+ */
+s.IMAGE = "image";
+
+/**
+ * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
+ * <script> tag.
+ *
+ * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
+ * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
+ * only tag-loaded scripts are injected.
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @since 0.6.0
+ */
+s.JAVASCRIPT = "javascript";
+
+/**
+ * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
+ * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
+ * must contain a matching wrapper function.
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @since 0.6.0
+ */
+s.JSON = "json";
+
+/**
+ * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
+ * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
+ * property is set to.
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @since 0.6.0
+ */
+s.JSONP = "jsonp";
+
+/**
+ * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
+ * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
+ * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
+ * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.6.0
+ */
+s.MANIFEST = "manifest";
+
+/**
+ * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
+ * <audio> tag.
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @since 0.6.0
+ */
+s.SOUND = "sound";
+
+/**
+ * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
+ * <video> tag.
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @since 0.6.0
+ */
+s.VIDEO = "video";
+
+/**
+ * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
+ * @property SPRITESHEET
+ * @type {String}
+ * @default spritesheet
+ * @static
+ * @since 0.6.0
+ */
+s.SPRITESHEET = "spritesheet";
+
+/**
+ * The preload type for SVG files.
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @since 0.6.0
+ */
+s.SVG = "svg";
+
+/**
+ * The preload type for text files, which is also the default file type if the type can not be determined. Text is
+ * loaded as raw text.
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @since 0.6.0
+ */
+s.TEXT = "text";
+
+/**
+ * The preload type for xml files. XML is loaded into an XML document.
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @since 0.6.0
+ */
+s.XML = "xml";
+
+// Events
+/**
+ * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
+ * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event progress
+ * @since 0.3.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
+ * @event loadstart
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.1
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
+ * @event complete
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.0
+ */
+
+/**
+ * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
+ * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
+ * just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event error
+ * @since 0.3.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
+ * This enables loaders to maintain internal queues, and surface file load errors.
+ * @event fileerror
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The even type ("fileerror")
+ * @param {LoadItem|object} The item that encountered the error
+ * @since 0.6.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
+ * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
+ * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
+ * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("fileload")
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.6.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
+ * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
+ * @event initialize
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("initialize")
+ * @param {AbstractLoader} loader The loader that has been initialized.
+ */
+
+
+/**
+ * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
+ * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
+ * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @method getItem
+ * @return {Object} The manifest item that this loader is responsible for loading.
+ * @since 0.6.0
+ */
+p.getItem = function () {
+ return this._item;
+};
+
+/**
+ * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
+ * event is dispatched.
+ * @method getResult
+ * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
+ * data (if it exists).
+ * @return {Object}
+ * @since 0.6.0
+ */
+p.getResult = function (raw) {
+ return raw ? this._rawResult : this._result;
+};
+
+/**
+ * Return the `tag` this object creates or uses for loading.
+ * @method getTag
+ * @return {Object} The tag instance
+ * @since 0.6.0
+ */
+p.getTag = function () {
+ return this._tag;
+};
+
+/**
+ * Set the `tag` this item uses for loading.
+ * @method setTag
+ * @param {Object} tag The tag instance
+ * @since 0.6.0
+ */
+p.setTag = function (tag) {
+ this._tag = tag;
+};
+
+/**
+ * Begin loading the item. This method is required when using a loader by itself.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.on("complete", handleComplete);
+ * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
+ * queue.load();
+ *
+ * @method load
+ */
+p.load = function () {
+ this._createRequest();
+
+ this._request.on("complete", this, this);
+ this._request.on("progress", this, this);
+ this._request.on("loadStart", this, this);
+ this._request.on("abort", this, this);
+ this._request.on("timeout", this, this);
+ this._request.on("error", this, this);
+
+ var evt = new Event("initialize");
+ evt.loader = this._request;
+ this.dispatchEvent(evt);
+
+ this._request.load();
+};
+
+/**
+ * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
+ * the background), but events will not longer be dispatched.
+ * @method cancel
+ */
+p.cancel = function () {
+ this.canceled = true;
+ this.destroy();
+};
+
+/**
+ * Clean up the loader.
+ * @method destroy
+ */
+p.destroy = function () {
+ if (this._request) {
+ this._request.removeAllEventListeners();
+ this._request.destroy();
+ }
+
+ this._request = null;
+
+ this._item = null;
+ this._rawResult = null;
+ this._result = null;
+
+ this._loadItems = null;
+
+ this.removeAllEventListeners();
+};
+
+/**
+ * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to expose items it loads internally.
+ * @method getLoadedItems
+ * @return {Array} A list of the items loaded by the loader.
+ * @since 0.6.0
+ */
+p.getLoadedItems = function () {
+ return this._loadedItems;
+};
+
+
+// Private methods
+/**
+ * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
+ * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
+ * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
+ * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
+ * @method _createRequest
+ * @protected
+ */
+p._createRequest = function () {
+ if (!this._preferXHR) {
+ this._request = new TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ } else {
+ this._request = new XHRRequest(this._item);
+ }
+};
+
+/**
+ * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
+ * by loaders that require tag loading.
+ * @method _createTag
+ * @param {String} src The tag source
+ * @return {HTMLElement} The tag that was created
+ * @protected
+ */
+p._createTag = function (src) {
+ return null;
+};
+
+/**
+ * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendLoadStart
+ * @protected
+ */
+p._sendLoadStart = function () {
+ if (this._isCanceled()) {
+ return;
+ }
+ this.dispatchEvent("loadstart");
+};
+
+/**
+ * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
+ * @method _sendProgress
+ * @param {Number | Object} value The progress of the loaded item, or an object containing loaded
+ * and total
properties.
+ * @protected
+ */
+p._sendProgress = function (value) {
+ if (this._isCanceled()) {
+ return;
+ }
+ var event = null;
+ if (typeof(value) == "number") {
+ this.progress = value;
+ event = new ProgressEvent(this.progress);
+ } else {
+ event = value;
+ this.progress = value.loaded / value.total;
+ event.progress = this.progress;
+ if (isNaN(this.progress) || this.progress == Infinity) {
+ this.progress = 0;
+ }
+ }
+ this.hasEventListener("progress") && this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
+ * @method _sendComplete
+ * @protected
+ */
+p._sendComplete = function () {
+ if (this._isCanceled()) {
+ return;
+ }
+
+ this.loaded = true;
+
+ var event = new Event("complete");
+ event.rawResult = this._rawResult;
+
+ if (this._result != null) {
+ event.result = this._result;
+ }
+
+ this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendError
+ * @param {ErrorEvent} event The event object containing specific error properties.
+ * @protected
+ */
+p._sendError = function (event) {
+ if (this._isCanceled() || !this.hasEventListener("error")) {
+ return;
+ }
+ if (event == null) {
+ event = new ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
+ }
+ this.dispatchEvent(event);
+};
+
+/**
+ * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
+ * do not cause issues after the queue has been cleaned up.
+ * @method _isCanceled
+ * @return {Boolean} If the loader has been canceled.
+ * @protected
+ */
+p._isCanceled = function () {
+ if (window.createjs == null || this.canceled) {
+ return true;
+ }
+ return false;
+};
+
+/**
+ * A custom result formatter function, which is called just before a request dispatches its complete event. Most
+ * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
+ * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
+ * @property resultFormatter
+ * @type Function
+ * @return {Object} The formatted result
+ * @since 0.6.0
+ */
+p.resultFormatter = null;
+
+/**
+ * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
+ * this method can be overridden for custom behaviours.
+ * @method handleEvent
+ * @param {Event} event The event that the internal request dispatches.
+ * @protected
+ * @since 0.6.0
+ */
+p.handleEvent = function (event) {
+ switch (event.type) {
+ case "complete":
+ this._rawResult = event.target._response;
+ var result = this.resultFormatter && this.resultFormatter(this);
+ if (result instanceof Function) {
+ result.call(this,
+ proxy(this._resultFormatSuccess, this),
+ proxy(this._resultFormatFailed, this)
+ );
+ } else {
+ this._result = result || this._rawResult;
+ this._sendComplete();
+ }
+ break;
+ case "progress":
+ this._sendProgress(event);
+ break;
+ case "error":
+ this._sendError(event);
+ break;
+ case "loadstart":
+ this._sendLoadStart();
+ break;
+ case "abort":
+ case "timeout":
+ if (!this._isCanceled()) {
+ this.dispatchEvent(new ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR"));
+ }
+ break;
+ }
+};
+
+/**
+ * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} result The formatted result
+ * @private
+ */
+p._resultFormatSuccess = function (result) {
+ this._result = result;
+ this._sendComplete();
+};
+
+/**
+ * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} error The error event
+ * @private
+ */
+p._resultFormatFailed = function (event) {
+ this._sendError(event);
+};
+
+/**
+ * @method buildPath
+ * @protected
+ * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
+ * instead.
+ */
+p.buildPath = function (src, data) {
+ return RequestUtils.buildPath(src, data);
+};
+
+/**
+ * @method toString
+ * @return {String} a string representation of the instance.
+ */
+p.toString = function () {
+ return "[PreloadJS AbstractLoader]";
+};
+
+module.exports = AbstractLoader = promote(AbstractLoader, "EventDispatcher");
+
+},{"../../createjs/events/ErrorEvent":1,"../../createjs/events/Event":2,"../../createjs/events/EventDispatcher":3,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"../data/LoadItem":8,"../events/ProgressEvent":9,"../net/TagRequest":13,"../net/XHRRequest":14,"../utils/RequestUtils":15}],11:[function(_dereq_,module,exports){
+/*
+ * ImageLoader
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+// constructor
+/**
+ * A loader for image files.
+ * @class ImageLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractLoader
+ * @constructor
+ */
+
+var AbstractLoader = _dereq_('./AbstractLoader');
+var RequestUtils = _dereq_('../utils/RequestUtils');
+var extend = _dereq_('../../createjs/utils/extend');
+var promote = _dereq_('../../createjs/utils/promote');
+var proxy = _dereq_('../../createjs/utils/proxy');
+
+function ImageLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, AbstractLoader.IMAGE);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "src";
+
+ // Check if the preload item is already a tag.
+ if (RequestUtils.isImageTag(loadItem)) {
+ this._tag = loadItem;
+ } else if (RequestUtils.isImageTag(loadItem.src)) {
+ this._tag = loadItem.src;
+ } else if (RequestUtils.isImageTag(loadItem.tag)) {
+ this._tag = loadItem.tag;
+ }
+
+ if (this._tag != null) {
+ this._preferXHR = false;
+ } else {
+ this._tag = document.createElement("img");
+ }
+
+ this.on("initialize", this._updateXHR, this);
+};
+
+var p = extend(ImageLoader, AbstractLoader);
+var s = ImageLoader;
+
+// static methods
+/**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+s.canLoadItem = function (item) {
+ return item.type == AbstractLoader.IMAGE;
+};
+
+// public methods
+p.load = function () {
+ if (this._tag.src != "" && this._tag.complete) {
+ this._sendComplete();
+ return;
+ }
+
+ var crossOrigin = this._item.crossOrigin;
+ if (crossOrigin == true) {
+ crossOrigin = "Anonymous";
+ }
+ if (crossOrigin != null && !RequestUtils.isLocal(this._item.src)) {
+ this._tag.crossOrigin = crossOrigin;
+ }
+
+ this.AbstractLoader_load();
+};
+
+// protected methods
+/**
+ * Before the item loads, set its mimeType and responseType.
+ * @property _updateXHR
+ * @param {Event} event
+ * @private
+ */
+p._updateXHR = function (event) {
+ event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';
+
+ // Only exists for XHR
+ if (event.loader.setResponseType) {
+ event.loader.setResponseType("blob");
+ }
+};
+
+/**
+ * The result formatter for Image files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLImageElement}
+ * @private
+ */
+p._formatResult = function (loader) {
+ return this._formatImage;
+};
+
+/**
+ * The asynchronous image formatter function. This is required because images have
+ * a short delay before they are ready.
+ * @method _formatImage
+ * @param {Function} successCallback The method to call when the result has finished formatting
+ * @param {Function} errorCallback The method to call if an error occurs during formatting
+ * @private
+ */
+p._formatImage = function (successCallback, errorCallback) {
+ var tag = this._tag;
+ var URL = window.URL || window.webkitURL;
+
+ if (!this._preferXHR) {
+ //document.body.removeChild(tag);
+ } else if (URL) {
+ var objURL = URL.createObjectURL(this.getResult(true));
+ tag.src = objURL;
+
+ tag.addEventListener("load", this._cleanUpURL, false);
+ tag.addEventListener("error", this._cleanUpURL, false);
+ } else {
+ tag.src = this._item.src;
+ }
+
+ if (tag.complete) {
+ successCallback(tag);
+ } else {
+ tag.onload = proxy(function () {
+ successCallback(this._tag);
+ }, this);
+
+ tag.onerror = proxy(function () {
+ errorCallback(_this._tag);
+ }, this);
+ }
+};
+
+/**
+ * Clean up the ObjectURL, the tag is done with it. Note that this function is run
+ * as an event listener without a proxy/closure, as it doesn't require it - so do not
+ * include any functionality that requires scope without changing it.
+ * @method _cleanUpURL
+ * @param event
+ * @private
+ */
+p._cleanUpURL = function (event) {
+ var URL = window.URL || window.webkitURL;
+ URL.revokeObjectURL(event.target.src);
+};
+
+var ImageLoader = promote(ImageLoader, "AbstractLoader");
+module.exports = ImageLoader;
+
+},{"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"../utils/RequestUtils":15,"./AbstractLoader":10}],12:[function(_dereq_,module,exports){
+/*
+ * AbstractRequest
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var promote = _dereq_('../../createjs/utils/promote');
+var extend = _dereq_('../../createjs/utils/extend');
+var EventDispatcher = _dereq_('../../createjs/events/EventDispatcher');
+
+/**
+ * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
+ * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
+ * hood to get data.
+ * @class AbstractRequest
+ * @param {LoadItem} item
+ * @constructor
+ */
+var AbstractRequest = function (item) {
+ this._item = item;
+};
+
+var p = extend(AbstractRequest, EventDispatcher);
+
+// public methods
+/**
+ * Begin a load.
+ * @method load
+ */
+p.load = function () {
+};
+
+/**
+ * Clean up a request.
+ * @method destroy
+ */
+p.destroy = function () {
+};
+
+/**
+ * Cancel an in-progress request.
+ * @method cancel
+ */
+p.cancel = function () {
+};
+
+module.exports = AbstractRequest = promote(AbstractRequest, "EventDispatcher");
+
+},{"../../createjs/events/EventDispatcher":3,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5}],13:[function(_dereq_,module,exports){
+/*
+ * TagRequest
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var proxy = _dereq_('../../createjs/utils/proxy');
+var extend = _dereq_('../../createjs/utils/extend');
+var AbstractRequest = _dereq_('./AbstractRequest');
+var Event = _dereq_('../../createjs/events/Event');
+var promote = _dereq_('../../createjs/utils/promote');
+
+// constructor
+/**
+ * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
+ * @class TagRequest
+ * @param {LoadItem} loadItem
+ * @param {HTMLElement} tag
+ * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
+ */
+function TagRequest(loadItem, tag, srcAttribute) {
+ this.AbstractRequest_constructor(loadItem);
+
+ // protected properties
+ /**
+ * The HTML tag instance that is used to load.
+ * @property _tag
+ * @type {HTMLElement}
+ * @protected
+ */
+ this._tag = tag;
+
+ /**
+ * The tag attribute that specifies the source, such as "src", "href", etc.
+ * @property _tagSrcAttribute
+ * @type {String}
+ * @protected
+ */
+ this._tagSrcAttribute = srcAttribute;
+
+ /**
+ * A method closure used for handling the tag load event.
+ * @property _loadedHandler
+ * @type {Function}
+ * @private
+ */
+ this._loadedHandler = proxy(this._handleTagComplete, this);
+
+ /**
+ * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
+ * @property _addedToDOM
+ * @type {Boolean}
+ * @private
+ */
+ this._addedToDOM = false;
+
+ /**
+ * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
+ *
+ * @type {null}
+ * @private
+ */
+ this._startTagVisibility = null;
+};
+
+var p = extend(TagRequest, AbstractRequest);
+
+// public methods
+p.load = function () {
+ this._tag.onload = proxy(this._handleTagComplete, this);
+ this._tag.onreadystatechange = proxy(this._handleReadyStateChange, this);
+ this._tag.onerror = proxy(this._handleError, this);
+
+ var evt = new Event("initialize");
+ evt.loader = this._tag;
+
+ this.dispatchEvent(evt);
+
+ this._hideTag();
+
+ this._loadTimeout = setTimeout(proxy(this._handleTimeout, this), this._item.loadTimeout);
+
+ this._tag[this._tagSrcAttribute] = this._item.src;
+
+ // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
+ if (this._tag.parentNode == null) {
+ window.document.body.appendChild(this._tag);
+ this._addedToDOM = true;
+ }
+};
+
+p.destroy = function () {
+ this._clean();
+ this._tag = null;
+
+ this.AbstractRequest_destroy();
+};
+
+// private methods
+/**
+ * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
+ * and LINK tags), but other cases may exist.
+ * @method _handleReadyStateChange
+ * @private
+ */
+p._handleReadyStateChange = function () {
+ clearTimeout(this._loadTimeout);
+ // This is strictly for tags in browsers that do not support onload.
+ var tag = this._tag;
+
+ // Complete is for old IE support.
+ if (tag.readyState == "loaded" || tag.readyState == "complete") {
+ this._handleTagComplete();
+ }
+};
+
+/**
+ * Handle any error events from the tag.
+ * @method _handleError
+ * @protected
+ */
+p._handleError = function () {
+ this._clean();
+ this.dispatchEvent("error");
+};
+
+/**
+ * Handle the tag's onload callback.
+ * @method _handleTagComplete
+ * @private
+ */
+p._handleTagComplete = function () {
+ this._rawResult = this._tag;
+ this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;
+
+ this._clean();
+ this._showTag();
+
+ this.dispatchEvent("complete");
+};
+
+/**
+ * The tag request has not loaded within the time specified in loadTimeout.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+p._handleTimeout = function () {
+ this._clean();
+ this.dispatchEvent(new Event("timeout"));
+};
+
+/**
+ * Remove event listeners, but don't destroy the request object
+ * @method _clean
+ * @private
+ */
+p._clean = function () {
+ this._tag.onload = null;
+ this._tag.onreadystatechange = null;
+ this._tag.onerror = null;
+ if (this._addedToDOM && this._tag.parentNode != null) {
+ this._tag.parentNode.removeChild(this._tag);
+ }
+ clearTimeout(this._loadTimeout);
+};
+
+p._hideTag = function () {
+ this._startTagVisibility = this._tag.style.visibility;
+ this._tag.style.visibility = "hidden";
+};
+
+p._showTag = function () {
+ this._tag.style.visibility = this._startTagVisibility;
+};
+
+/**
+ * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
+ * that is already in a load, but not complete.
+ * @method _handleStalled
+ * @private
+ */
+p._handleStalled = function () {
+ //Ignore, let the timeout take care of it. Sometimes its not really stopped.
+};
+
+module.exports = promote(TagRequest, "AbstractRequest");
+},{"../../createjs/events/Event":2,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"./AbstractRequest":12}],14:[function(_dereq_,module,exports){
+/*
+ * XHRRequest
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var proxy = _dereq_('../../createjs/utils/proxy');
+var extend = _dereq_('../../createjs/utils/extend');
+var promote = _dereq_('../../createjs/utils/promote');
+var AbstractRequest = _dereq_('./AbstractRequest');
+var AbstractLoader = _dereq_('../loaders/AbstractLoader');
+var RequestUtils = _dereq_('../utils/RequestUtils');
+var ErrorEvent = _dereq_('../../createjs/events/ErrorEvent');
+var ProgressEvent = _dereq_('../events/ProgressEvent');
+
+/**
+ * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
+ * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
+ * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
+ * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
+ * cross-domain loading.
+ * @class XHRRequest
+ * @constructor
+ * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * for an overview of supported file properties.
+ * @extends AbstractLoader
+ */
+function XHRRequest(item) {
+ this.AbstractRequest_constructor(item);
+
+ // protected properties
+ /**
+ * A reference to the XHR request used to load the content.
+ * @property _request
+ * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
+ * @private
+ */
+ this._request = null;
+
+ /**
+ * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
+ * typically IE9).
+ * @property _loadTimeout
+ * @type {Number}
+ * @private
+ */
+ this._loadTimeout = null;
+
+ /**
+ * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
+ * the version, so we use capabilities to make a best guess.
+ * @property _xhrLevel
+ * @type {Number}
+ * @default 1
+ * @private
+ */
+ this._xhrLevel = 1;
+
+ /**
+ * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
+ * null until the file is loaded.
+ * @property _response
+ * @type {mixed}
+ * @private
+ */
+ this._response = null;
+
+ /**
+ * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
+ * an HTML tag or a formatted object which is set to the result
property, but the developer may still
+ * want to access the raw content as it was loaded.
+ * @property _rawResponse
+ * @type {String|Object}
+ * @private
+ */
+ this._rawResponse = null;
+
+ this._canceled = false;
+
+ // Setup our event handlers now.
+ this._handleLoadStartProxy = proxy(this._handleLoadStart, this);
+ this._handleProgressProxy = proxy(this._handleProgress, this);
+ this._handleAbortProxy = proxy(this._handleAbort, this);
+ this._handleErrorProxy = proxy(this._handleError, this);
+ this._handleTimeoutProxy = proxy(this._handleTimeout, this);
+ this._handleLoadProxy = proxy(this._handleLoad, this);
+ this._handleReadyStateChangeProxy = proxy(this._handleReadyStateChange, this);
+
+ if (!this._createXHR(item)) {
+ //TODO: Throw error?
+ }
+};
+
+var p = extend(XHRRequest, AbstractRequest);
+
+// static properties
+/**
+ * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
+ * @property ACTIVEX_VERSIONS
+ * @type {Array}
+ * @since 0.4.2
+ * @private
+ */
+XHRRequest.ACTIVEX_VERSIONS = [
+ "Msxml2.XMLHTTP.6.0",
+ "Msxml2.XMLHTTP.5.0",
+ "Msxml2.XMLHTTP.4.0",
+ "MSXML2.XMLHTTP.3.0",
+ "MSXML2.XMLHTTP",
+ "Microsoft.XMLHTTP"
+];
+
+// Public methods
+/**
+ * Look up the loaded result.
+ * @method getResult
+ * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the
+ * HTML head.
+ * - A style tag for CSS (<style />)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - An binary arraybuffer loaded by XHR
+ *
+ * Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+p.getResult = function (raw) {
+ if (raw && this._rawResponse) {
+ return this._rawResponse;
+ }
+ return this._response;
+};
+
+// Overrides abstract method in AbstractRequest
+p.cancel = function () {
+ this.canceled = true;
+ this._clean();
+ this._request.abort();
+};
+
+// Overrides abstract method in AbstractLoader
+p.load = function () {
+ if (this._request == null) {
+ this._handleError();
+ return;
+ }
+
+ //Events
+ if (this._request.addEventListener != null) {
+ this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
+ this._request.addEventListener("progress", this._handleProgressProxy, false);
+ this._request.addEventListener("abort", this._handleAbortProxy, false);
+ this._request.addEventListener("error", this._handleErrorProxy, false);
+ this._request.addEventListener("timeout", this._handleTimeoutProxy, false);
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.addEventListener("load", this._handleLoadProxy, false);
+ this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
+ } else {
+ // IE9 support
+ this._request.onloadstart = this._handleLoadStartProxy;
+ this._request.onprogress = this._handleProgressProxy;
+ this._request.onabort = this._handleAbortProxy;
+ this._request.onerror = this._handleErrorProxy;
+ this._request.ontimeout = this._handleTimeoutProxy;
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.onload = this._handleLoadProxy;
+ this._request.onreadystatechange = this._handleReadyStateChangeProxy;
+ }
+
+ // Set up a timeout if we don't have XHR2
+ if (this._xhrLevel == 1) {
+ this._loadTimeout = setTimeout(proxy(this._handleTimeout, this), this._item.loadTimeout);
+ }
+
+ // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome
+ try {
+ if (!this._item.values || this._item.method == AbstractLoader.GET) {
+ this._request.send();
+ } else if (this._item.method == AbstractLoader.POST) {
+ this._request.send(RequestUtils.formatQueryString(this._item.values));
+ }
+ } catch (error) {
+ this.dispatchEvent(new ErrorEvent("XHR_SEND", null, error));
+ }
+};
+
+p.setResponseType = function (type) {
+ // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
+ if (type === 'blob') {
+ type = window.URL ? 'blob' : 'arraybuffer';
+ this._responseType = type;
+ }
+ this._request.responseType = type;
+};
+
+/**
+ * Get all the response headers from the XmlHttpRequest.
+ *
+ * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match
+ * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
+ * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
+ * pair.
+ * @method getAllResponseHeaders
+ * @return {String}
+ * @since 0.4.1
+ */
+p.getAllResponseHeaders = function () {
+ if (this._request.getAllResponseHeaders instanceof Function) {
+ return this._request.getAllResponseHeaders();
+ } else {
+ return null;
+ }
+};
+
+/**
+ * Get a specific response header from the XmlHttpRequest.
+ *
+ * From the docs: Returns the header field value from the response of which the field name matches
+ * header, unless the field name is Set-Cookie or Set-Cookie2.
+ * @method getResponseHeader
+ * @param {String} header The header name to retrieve.
+ * @return {String}
+ * @since 0.4.1
+ */
+p.getResponseHeader = function (header) {
+ if (this._request.getResponseHeader instanceof Function) {
+ return this._request.getResponseHeader(header);
+ } else {
+ return null;
+ }
+};
+
+// protected methods
+/**
+ * The XHR request has reported progress.
+ * @method _handleProgress
+ * @param {Object} event The XHR progress event.
+ * @private
+ */
+p._handleProgress = function (event) {
+ if (!event || event.loaded > 0 && event.total == 0) {
+ return; // Sometimes we get no "total", so just ignore the progress event.
+ }
+
+ var newEvent = new ProgressEvent(event.loaded, event.total);
+ this.dispatchEvent(newEvent);
+};
+
+/**
+ * The XHR request has reported a load start.
+ * @method _handleLoadStart
+ * @param {Object} event The XHR loadStart event.
+ * @private
+ */
+p._handleLoadStart = function (event) {
+ clearTimeout(this._loadTimeout);
+ this.dispatchEvent("loadstart");
+};
+
+/**
+ * The XHR request has reported an abort event.
+ * @method handleAbort
+ * @param {Object} event The XHR abort event.
+ * @private
+ */
+p._handleAbort = function (event) {
+ this._clean();
+ this.dispatchEvent(new ErrorEvent("XHR_ABORTED", null, event));
+};
+
+/**
+ * The XHR request has reported an error event.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+p._handleError = function (event) {
+ this._clean();
+ this.dispatchEvent(new ErrorEvent(event.message));
+};
+
+/**
+ * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
+ * event, so we must monitor the readyStateChange to determine if the file is loaded.
+ * @method _handleReadyStateChange
+ * @param {Object} event The XHR readyStateChange event.
+ * @private
+ */
+p._handleReadyStateChange = function (event) {
+ if (this._request.readyState == 4) {
+ this._handleLoad();
+ }
+};
+
+/**
+ * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
+ * request.readyState == 4
. Only the first call to this method will be processed.
+ * @method _handleLoad
+ * @param {Object} event The XHR load event.
+ * @private
+ */
+p._handleLoad = function (event) {
+ if (this.loaded) {
+ return;
+ }
+ this.loaded = true;
+
+ var error = this._checkError();
+ if (error) {
+ this._handleError(error);
+ return;
+ }
+
+ this._response = this._getResponse();
+ // Convert arraybuffer back to blob
+ if (this._responseType === 'arraybuffer') {
+ try {
+ this._response = new Blob([this._response]);
+ } catch (e) {
+ // Fallback to use BlobBuilder if Blob constructor is not supported
+ // Tested on Android 2.3 ~ 4.2 and iOS5 safari
+ window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ if (e.name === 'TypeError' && window.BlobBuilder) {
+ var builder = new BlobBuilder();
+ builder.append(this._response);
+ this._response = builder.getBlob();
+ }
+ }
+ }
+ this._clean();
+
+ this.dispatchEvent(new Event("complete"));
+};
+
+/**
+ * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout
+ * callback.
+ * @method _handleTimeout
+ * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
+ * @private
+ */
+p._handleTimeout = function (event) {
+ this._clean();
+
+ this.dispatchEvent(new ErrorEvent("PRELOAD_TIMEOUT", null, event));
+};
+
+// Protected
+/**
+ * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
+ * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
+ * @method _checkError
+ * @return {int} If the request status returns an error code.
+ * @private
+ */
+p._checkError = function () {
+ //LM: Probably need additional handlers here, maybe 501
+ var status = parseInt(this._request.status);
+
+ switch (status) {
+ case 404: // Not Found
+ case 0: // Not Loaded
+ return new Error(status);
+ }
+ return null;
+};
+
+/**
+ * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
+ * in other browsers. If there is no response, the _response
property will remain null.
+ * @method _getResponse
+ * @private
+ */
+p._getResponse = function () {
+ if (this._response != null) {
+ return this._response;
+ }
+
+ if (this._request.response != null) {
+ return this._request.response;
+ }
+
+ // Android 2.2 uses .responseText
+ try {
+ if (this._request.responseText != null) {
+ return this._request.responseText;
+ }
+ } catch (e) {
+ }
+
+ // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
+ try {
+ if (this._request.responseXML != null) {
+ return this._request.responseXML;
+ }
+ } catch (e) {
+ }
+
+ return null;
+};
+
+/**
+ * Create an XHR request. Depending on a number of factors, we get totally different results.
+ * - Some browsers get an
XDomainRequest
when loading cross-domain.
+ * - XMLHttpRequest are created when available.
+ * - ActiveX.XMLHTTP objects are used in older IE browsers.
+ * - Text requests override the mime type if possible
+ * - Origin headers are sent for crossdomain requests in some browsers.
+ * - Binary loads set the response type to "arraybuffer"
+ * @method _createXHR
+ * @param {Object} item The requested item that is being loaded.
+ * @return {Boolean} If an XHR request or equivalent was successfully created.
+ * @private
+ */
+p._createXHR = function (item) {
+ // Check for cross-domain loads. We can't fully support them, but we can try.
+ var crossdomain = RequestUtils.isCrossDomain(item);
+ var headers = {};
+
+ // Create the request. Fallback to whatever support we have.
+ var req = null;
+ if (window.XMLHttpRequest) {
+ req = new XMLHttpRequest();
+ // This is 8 or 9, so use XDomainRequest instead.
+ if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
+ req = new XDomainRequest();
+ }
+ } else { // Old IE versions use a different approach
+ for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
+ var axVersion = s.ACTIVEX_VERSIONS[i];
+ try {
+ req = new ActiveXObject(axVersion);
+ break;
+ } catch (e) {
+ }
+ }
+ if (req == null) {
+ return false;
+ }
+ }
+
+ // Default to utf-8 for Text requests.
+ if (item.mimeType == null && RequestUtils.isText(item.type)) {
+ item.mimeType = "text/plain; charset=utf-8";
+ }
+
+ // IE9 doesn't support overrideMimeType(), so we need to check for it.
+ if (item.mimeType && req.overrideMimeType) {
+ req.overrideMimeType(item.mimeType);
+ }
+
+ // Determine the XHR level
+ this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;
+
+ var src = null;
+ if (item.method == AbstractLoader.GET) {
+ src = RequestUtils.buildPath(item.src, item.values);
+ } else {
+ src = item.src;
+ }
+
+ // Open the request. Set cross-domain flags if it is supported (XHR level 1 only)
+ req.open(item.method || AbstractLoader.GET, src, true);
+
+ if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
+ headers["Origin"] = location.origin;
+ }
+
+ // To send data we need to set the Content-type header)
+ if (item.values && item.method == AbstractLoader.POST) {
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+
+ if (!crossdomain && !headers["X-Requested-With"]) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ if (item.headers) {
+ for (var n in item.headers) {
+ headers[n] = item.headers[n];
+ }
+ }
+
+ for (n in headers) {
+ req.setRequestHeader(n, headers[n])
+ }
+
+ if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
+ req.withCredentials = item.withCredentials;
+ }
+
+ this._request = req;
+
+ return true;
+};
+
+/**
+ * A request has completed (or failed or canceled), and needs to be disposed.
+ * @method _clean
+ * @private
+ */
+p._clean = function () {
+ clearTimeout(this._loadTimeout);
+
+ if (this._request.removeEventListener != null) {
+ this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
+ this._request.removeEventListener("progress", this._handleProgressProxy);
+ this._request.removeEventListener("abort", this._handleAbortProxy);
+ this._request.removeEventListener("error", this._handleErrorProxy);
+ this._request.removeEventListener("timeout", this._handleTimeoutProxy);
+ this._request.removeEventListener("load", this._handleLoadProxy);
+ this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
+ } else {
+ this._request.onloadstart = null;
+ this._request.onprogress = null;
+ this._request.onabort = null;
+ this._request.onerror = null;
+ this._request.ontimeout = null;
+ this._request.onload = null;
+ this._request.onreadystatechange = null;
+ }
+};
+
+p.toString = function () {
+ return "[PreloadJS XHRRequest]";
+};
+
+module.exports = XHRRequest = promote(XHRRequest, "AbstractRequest");
+
+},{"../../createjs/events/ErrorEvent":1,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"../events/ProgressEvent":9,"../loaders/AbstractLoader":10,"../utils/RequestUtils":15,"./AbstractRequest":12}],15:[function(_dereq_,module,exports){
+/*
+ * RequestUtils
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+
+var AbstractLoader = _dereq_('../loaders/AbstractLoader');
+
+/**
+ * Utilities that assist with parsing load items, and determining file types, etc.
+ * @class RequestUtils
+ */
+var s = {};
+
+/**
+ * The Regular Expression used to test file URLS for an absolute path.
+ * @property ABSOLUTE_PATH
+ * @type {RegExp}
+ * @static
+ */
+s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
+
+/**
+ * The Regular Expression used to test file URLS for a relative path.
+ * @property RELATIVE_PATH
+ * @type {RegExp}
+ * @static
+ */
+s.RELATIVE_PATT = (/^[./]*?\//i);
+
+/**
+ * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
+ * removed.
+ * @property EXTENSION_PATT
+ * @type {RegExp}
+ * @static
+ */
+s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
+
+/**
+ * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
+ *
+ * - If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
+ * `//networkPath`)
+ * - If the path is relative. Relative paths start with `../` or `/path` (or similar)
+ * - The file extension. This is determined by the filename with an extension. Query strings are dropped, and
+ * the file path is expected to follow the format `name.ext`.
+ *
+ * @method parseURI
+ * @param {String} path
+ * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
+ * property, which is the lowercase extension.
+ * @static
+ */
+s.parseURI = function (path) {
+ var info = {absolute: false, relative: false};
+ if (path == null) {
+ return info;
+ }
+
+ // Drop the query string
+ var queryIndex = path.indexOf("?");
+ if (queryIndex > -1) {
+ path = path.substr(0, queryIndex);
+ }
+
+ // Absolute
+ var match;
+ if (s.ABSOLUTE_PATT.test(path)) {
+ info.absolute = true;
+
+ // Relative
+ } else if (s.RELATIVE_PATT.test(path)) {
+ info.relative = true;
+ }
+
+ // Extension
+ if (match = path.match(s.EXTENSION_PATT)) {
+ info.extension = match[1].toLowerCase();
+ }
+ return info;
+};
+
+/**
+ * Formats an object into a query string for either a POST or GET request.
+ * @method formatQueryString
+ * @param {Object} data The data to convert to a query string.
+ * @param {Array} [query] Existing name/value pairs to append on to this query.
+ * @static
+ */
+s.formatQueryString = function (data, query) {
+ if (data == null) {
+ throw new Error('You must specify data.');
+ }
+ var params = [];
+ for (var n in data) {
+ params.push(n + '=' + escape(data[n]));
+ }
+ if (query) {
+ params = params.concat(query);
+ }
+ return params.join('&');
+};
+
+/**
+ * A utility method that builds a file path using a source and a data object, and formats it into a new path.
+ * @method buildPath
+ * @param {String} src The source path to add values to.
+ * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
+ * path will be preserved.
+ * @returns {string} A formatted string that contains the path and the supplied parameters.
+ * @static
+ */
+s.buildPath = function (src, data) {
+ if (data == null) {
+ return src;
+ }
+
+ var query = [];
+ var idx = src.indexOf('?');
+
+ if (idx != -1) {
+ var q = src.slice(idx + 1);
+ query = query.concat(q.split('&'));
+ }
+
+ if (idx != -1) {
+ return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
+ } else {
+ return src + '?' + this._formatQueryString(data, query);
+ }
+};
+
+/**
+ * @method isCrossDomain
+ * @param {LoadItem|Object} item A load item with a `src` property.
+ * @return {Boolean} If the load item is loading from a different domain than the current location.
+ * @static
+ */
+s.isCrossDomain = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+
+ var host = document.createElement("a");
+ host.href = location.href;
+
+ var crossdomain = (target.hostname != "") &&
+ (target.port != host.port ||
+ target.protocol != host.protocol ||
+ target.hostname != host.hostname);
+ return crossdomain;
+};
+
+/**
+ * @method isLocal
+ * @param {LoadItem|Object} item A load item with a `src` property
+ * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
+ * well.
+ * @static
+ */
+s.isLocal = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+ return target.hostname == "" && target.protocol == "file:";
+};
+
+/**
+ * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
+ * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play
+ * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
+ * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
+ * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @method isBinary
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is binary.
+ * @static
+ */
+s.isBinary = function (type) {
+ switch (type) {
+ case AbstractLoader.IMAGE:
+ case AbstractLoader.BINARY:
+ return true;
+ default:
+ return false;
+ }
+};
+
+/**
+ * Check if item is a valid HTMLImageElement
+ * @method isImageTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isImageTag = function (item) {
+ return item instanceof HTMLImageElement;
+};
+
+/**
+ * Check if item is a valid HTMLAudioElement
+ * @method isAudioTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isAudioTag = function (item) {
+ if (window.HTMLAudioElement) {
+ return item instanceof HTMLAudioElement;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Check if item is a valid HTMLVideoElement
+ * @method isVideoTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isVideoTag = function (item) {
+ if (window.HTMLVideoElement) {
+ return item instanceof HTMLVideoElement;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
+ * @method isText
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is text.
+ * @static
+ */
+s.isText = function (type) {
+ switch (type) {
+ case AbstractLoader.TEXT:
+ case AbstractLoader.JSON:
+ case AbstractLoader.MANIFEST:
+ case AbstractLoader.XML:
+ case AbstractLoader.CSS:
+ case AbstractLoader.SVG:
+ case AbstractLoader.JAVASCRIPT:
+ case AbstractLoader.SPRITESHEET:
+ return true;
+ default:
+ return false;
+ }
+};
+
+/**
+ * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
+ * if it is an unusual extension.
+ * @method getTypeByExtension
+ * @param {String} extension The file extension to use to determine the load type.
+ * @return {String} The determined load type (for example, AbstractLoader.IMAGE
). Will return `null` if
+ * the type can not be determined by the extension.
+ * @static
+ */
+s.getTypeByExtension = function (extension) {
+ if (extension == null) {
+ return AbstractLoader.TEXT;
+ }
+
+ switch (extension.toLowerCase()) {
+ case "jpeg":
+ case "jpg":
+ case "gif":
+ case "png":
+ case "webp":
+ case "bmp":
+ return AbstractLoader.IMAGE;
+ case "ogg":
+ case "mp3":
+ case "webm":
+ return AbstractLoader.SOUND;
+ case "mp4":
+ case "webm":
+ case "ts":
+ return AbstractLoader.VIDEO;
+ case "json":
+ return AbstractLoader.JSON;
+ case "xml":
+ return AbstractLoader.XML;
+ case "css":
+ return AbstractLoader.CSS;
+ case "js":
+ return AbstractLoader.JAVASCRIPT;
+ case 'svg':
+ return AbstractLoader.SVG;
+ default:
+ return AbstractLoader.TEXT;
+ }
+};
+
+var RequestUtils = s;
+module.exports = RequestUtils;
+
+},{"../loaders/AbstractLoader":10}],16:[function(_dereq_,module,exports){
+// File for legacy window.createjs support. Also used for the the build process.
+(function (name, definition) {
+ if (typeof module != 'undefined') module.exports = definition();
+ else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
+ else this[name] = definition(); console.log(this, name);
+}('createjs', function () {
+ console.log("createjs?");
+ return {
+ LoadQueue: _dereq_("./LoadQueue"),
+ promote: _dereq_('../createjs/utils/promote'),
+ extend: _dereq_('../createjs/utils/extend'),
+ Event: _dereq_('../createjs/events/Event'),
+ ErrorEvent: _dereq_('../createjs/events/ErrorEvent'),
+ ProgressEvent: _dereq_('./events/ProgressEvent')
+ };
+}));
+
+},{"../createjs/events/ErrorEvent":1,"../createjs/events/Event":2,"../createjs/utils/extend":4,"../createjs/utils/promote":5,"./LoadQueue":7,"./events/ProgressEvent":9}]},{},[16]);
+
+},{}],2:[function(require,module,exports){
+var build = require('../build');
+
+var label = document.createElement("div");
+label.innerText = "createjs exists! Its classes are: \n"+Object.keys(createjs).join("\n");
+document.body.appendChild(label);
+
+},{"../build":1}]},{},[2]);
diff --git a/examples/moduleLoaders/build.js b/examples/moduleLoaders/build.js
new file mode 100644
index 0000000..0e0fcf4
--- /dev/null
+++ b/examples/moduleLoaders/build.js
@@ -0,0 +1,5454 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oExample
+ *
+ * myObject.addEventListener("change", createjs.proxy(myMethod, scope));
+ *
+ * @module CreateJS
+ * @main CreateJS
+ */
+// constructor:
+/**
+ * Contains properties and methods shared by all events for use with
+ * {{#crossLink "EventDispatcher"}}{{/crossLink}}.
+ *
+ * Note that Event objects are often reused, so you should never
+ * rely on an event object's state outside of the call stack it was received in.
+ * @class Event
+ * @param {String} type The event type.
+ * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
+ * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
+ * @constructor
+ **/
+function Event(type, bubbles, cancelable) {
+
+
+ // public properties:
+ /**
+ * The type of event.
+ * @property type
+ * @type String
+ **/
+ this.type = type;
+
+ /**
+ * The object that generated an event.
+ * @property target
+ * @type Object
+ * @default null
+ * @readonly
+ */
+ this.target = null;
+
+ /**
+ * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
+ * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
+ * is generated from childObj, then a listener on parentObj would receive the event with
+ * target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
+ * @property currentTarget
+ * @type Object
+ * @default null
+ * @readonly
+ */
+ this.currentTarget = null;
+
+ /**
+ * For bubbling events, this indicates the current event phase:
+ * - capture phase: starting from the top parent to the target
+ * - at target phase: currently being dispatched from the target
+ * - bubbling phase: from the target to the top parent
+ *
+ * @property eventPhase
+ * @type Number
+ * @default 0
+ * @readonly
+ */
+ this.eventPhase = 0;
+
+ /**
+ * Indicates whether the event will bubble through the display list.
+ * @property bubbles
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.bubbles = !!bubbles;
+
+ /**
+ * Indicates whether the default behaviour of this event can be cancelled via
+ * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
+ * @property cancelable
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.cancelable = !!cancelable;
+
+ /**
+ * The epoch time at which this event was created.
+ * @property timeStamp
+ * @type Number
+ * @default 0
+ * @readonly
+ */
+ this.timeStamp = (new Date()).getTime();
+
+ /**
+ * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
+ * on this event.
+ * @property defaultPrevented
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.defaultPrevented = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
+ * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
+ * @property propagationStopped
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.propagationStopped = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
+ * on this event.
+ * @property immediatePropagationStopped
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.immediatePropagationStopped = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
+ * @property removed
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.removed = false;
+}
+var p = Event.prototype;
+
+/**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+// p.initialize = function() {}; // searchable for devs wondering where it is.
+
+
+// public methods:
+/**
+ * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method preventDefault
+ **/
+p.preventDefault = function () {
+ this.defaultPrevented = this.cancelable && true;
+};
+
+/**
+ * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method stopPropagation
+ **/
+p.stopPropagation = function () {
+ this.propagationStopped = true;
+};
+
+/**
+ * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
+ * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method stopImmediatePropagation
+ **/
+p.stopImmediatePropagation = function () {
+ this.immediatePropagationStopped = this.propagationStopped = true;
+};
+
+/**
+ * Causes the active listener to be removed via removeEventListener();
+ *
+ * myBtn.addEventListener("click", function(evt) {
+ * // do stuff...
+ * evt.remove(); // removes this listener.
+ * });
+ *
+ * @method remove
+ **/
+p.remove = function () {
+ this.removed = true;
+};
+
+/**
+ * Returns a clone of the Event instance.
+ * @method clone
+ * @return {Event} a clone of the Event instance.
+ **/
+p.clone = function () {
+ return new Event(this.type, this.bubbles, this.cancelable);
+};
+
+/**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the instance.
+ * @return {Event} Returns the instance the method is called on (useful for chaining calls.)
+ * @chainable
+ */
+p.set = function (props) {
+ for (var n in props) {
+ this[n] = props[n];
+ }
+ return this;
+};
+
+/**
+ * Returns a string representation of this object.
+ * @method toString
+ * @return {String} a string representation of the instance.
+ **/
+p.toString = function () {
+ return "[Event (type=" + this.type + ")]";
+};
+
+module.exports = Event;
+
+},{}],3:[function(_dereq_,module,exports){
+/*
+ * EventDispatcher
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ * Copyright (c) 2010 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module CreateJS
+ */
+
+
+var Event = _dereq_('./Event');
+
+// constructor:
+/**
+ * EventDispatcher provides methods for managing queues of event listeners and dispatching events.
+ *
+ * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
+ * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method.
+ *
+ * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the
+ * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports
+ * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent.
+ *
+ * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier
+ * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The
+ * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to
+ * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}.
+ *
+ * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}}
+ * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also
+ * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener.
+ *
+ * Example
+ * Add EventDispatcher capabilities to the "MyClass" class.
+ *
+ * EventDispatcher.initialize(MyClass.prototype);
+ *
+ * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}).
+ *
+ * instance.addEventListener("eventName", handlerMethod);
+ * function handlerMethod(event) {
+ * console.log(event.target + " Was Clicked");
+ * }
+ *
+ * Maintaining proper scope
+ * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}}
+ * method to subscribe to events simplifies this.
+ *
+ * instance.addEventListener("click", function(event) {
+ * console.log(instance == this); // false, scope is ambiguous.
+ * });
+ *
+ * instance.on("click", function(event) {
+ * console.log(instance == this); // true, "on" uses dispatcher scope by default.
+ * });
+ *
+ * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope.
+ *
+ *
+ * @class EventDispatcher
+ * @constructor
+ **/
+function EventDispatcher() {
+
+
+ // private properties:
+ /**
+ * @protected
+ * @property _listeners
+ * @type Object
+ **/
+ this._listeners = null;
+
+ /**
+ * @protected
+ * @property _captureListeners
+ * @type Object
+ **/
+ this._captureListeners = null;
+}
+var p = EventDispatcher.prototype;
+
+/**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+// p.initialize = function() {}; // searchable for devs wondering where it is.
+
+
+// static public methods:
+/**
+ * Static initializer to mix EventDispatcher methods into a target object or prototype.
+ *
+ * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class
+ * EventDispatcher.initialize(myObject); // add to a specific instance
+ *
+ * @method initialize
+ * @static
+ * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a
+ * prototype.
+ **/
+EventDispatcher.initialize = function (target) {
+ target.addEventListener = p.addEventListener;
+ target.on = p.on;
+ target.removeEventListener = target.off = p.removeEventListener;
+ target.removeAllEventListeners = p.removeAllEventListeners;
+ target.hasEventListener = p.hasEventListener;
+ target.dispatchEvent = p.dispatchEvent;
+ target._dispatchEvent = p._dispatchEvent;
+ target.willTrigger = p.willTrigger;
+};
+
+
+// public methods:
+/**
+ * Adds the specified event listener. Note that adding multiple listeners to the same function will result in
+ * multiple callbacks getting fired.
+ *
+ * Example
+ *
+ * displayObject.addEventListener("click", handleClick);
+ * function handleClick(event) {
+ * // Click happened.
+ * }
+ *
+ * @method addEventListener
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
+ * the event is dispatched.
+ * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ * @return {Function | Object} Returns the listener for chaining or assignment.
+ **/
+p.addEventListener = function (type, listener, useCapture) {
+ var listeners;
+ if (useCapture) {
+ listeners = this._captureListeners = this._captureListeners || {};
+ } else {
+ listeners = this._listeners = this._listeners || {};
+ }
+ var arr = listeners[type];
+ if (arr) {
+ this.removeEventListener(type, listener, useCapture);
+ }
+ arr = listeners[type]; // remove may have deleted the array
+ if (!arr) {
+ listeners[type] = [listener];
+ }
+ else {
+ arr.push(listener);
+ }
+ return listener;
+};
+
+/**
+ * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener
+ * only run once, associate arbitrary data with the listener, and remove the listener.
+ *
+ * This method works by creating an anonymous wrapper function and subscribing it with addEventListener.
+ * The created anonymous function is returned for use with .removeEventListener (or .off).
+ *
+ * Example
+ *
+ * var listener = myBtn.on("click", handleClick, null, false, {count:3});
+ * function handleClick(evt, data) {
+ * data.count -= 1;
+ * console.log(this == myBtn); // true - scope defaults to the dispatcher
+ * if (data.count == 0) {
+ * alert("clicked 3 times!");
+ * myBtn.off("click", listener);
+ * // alternately: evt.remove();
+ * }
+ * }
+ *
+ * @method on
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
+ * the event is dispatched.
+ * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent).
+ * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered.
+ * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called.
+ * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener.
+ **/
+p.on = function (type, listener, scope, once, data, useCapture) {
+ if (listener.handleEvent) {
+ scope = scope || listener;
+ listener = listener.handleEvent;
+ }
+ scope = scope || this;
+ return this.addEventListener(type, function (evt) {
+ listener.call(scope, evt, data);
+ once && evt.remove();
+ }, useCapture);
+};
+
+/**
+ * Removes the specified event listener.
+ *
+ * Important Note: that you must pass the exact function reference used when the event was added. If a proxy
+ * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or
+ * closure will not work.
+ *
+ * Example
+ *
+ * displayObject.removeEventListener("click", handleClick);
+ *
+ * @method removeEventListener
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener The listener function or object.
+ * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ **/
+p.removeEventListener = function (type, listener, useCapture) {
+ var listeners = useCapture ? this._captureListeners : this._listeners;
+ if (!listeners) {
+ return;
+ }
+ var arr = listeners[type];
+ if (!arr) {
+ return;
+ }
+ for (var i = 0, l = arr.length; i < l; i++) {
+ if (arr[i] == listener) {
+ if (l == 1) {
+ delete(listeners[type]);
+ } // allows for faster checks.
+ else {
+ arr.splice(i, 1);
+ }
+ break;
+ }
+ }
+};
+
+/**
+ * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the
+ * .on method.
+ *
+ * @method off
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener The listener function or object.
+ * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ **/
+p.off = p.removeEventListener;
+
+/**
+ * Removes all listeners for the specified type, or all listeners of all types.
+ *
+ * Example
+ *
+ * // Remove all listeners
+ * displayObject.removeAllEventListeners();
+ *
+ * // Remove all click listeners
+ * displayObject.removeAllEventListeners("click");
+ *
+ * @method removeAllEventListeners
+ * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed.
+ **/
+p.removeAllEventListeners = function (type) {
+ if (!type) {
+ this._listeners = this._captureListeners = null;
+ }
+ else {
+ if (this._listeners) {
+ delete(this._listeners[type]);
+ }
+ if (this._captureListeners) {
+ delete(this._captureListeners[type]);
+ }
+ }
+};
+
+/**
+ * Dispatches the specified event to all listeners.
+ *
+ * Example
+ *
+ * // Use a string event
+ * this.dispatchEvent("complete");
+ *
+ * // Use an Event instance
+ * var event = new createjs.Event("progress");
+ * this.dispatchEvent(event);
+ *
+ * @method dispatchEvent
+ * @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
+ * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
+ * dispatchEvent will construct an Event instance with the specified type.
+ * @return {Boolean} Returns the value of eventObj.defaultPrevented.
+ **/
+p.dispatchEvent = function (eventObj) {
+ if (typeof eventObj == "string") {
+ // won't bubble, so skip everything if there's no listeners:
+ var listeners = this._listeners;
+ if (!listeners || !listeners[eventObj]) {
+ return false;
+ }
+ eventObj = new Event(eventObj);
+ } else if (eventObj.target && eventObj.clone) {
+ // redispatching an active event object, so clone it:
+ eventObj = eventObj.clone();
+ }
+ try {
+ eventObj.target = this;
+ } catch (e) {
+ } // try/catch allows redispatching of native events
+
+ if (!eventObj.bubbles || !this.parent) {
+ this._dispatchEvent(eventObj, 2);
+ } else {
+ var top = this, list = [top];
+ while (top.parent) {
+ list.push(top = top.parent);
+ }
+ var i, l = list.length;
+
+ // capture & atTarget
+ for (i = l - 1; i >= 0 && !eventObj.propagationStopped; i--) {
+ list[i]._dispatchEvent(eventObj, 1 + (i == 0));
+ }
+ // bubbling
+ for (i = 1; i < l && !eventObj.propagationStopped; i++) {
+ list[i]._dispatchEvent(eventObj, 3);
+ }
+ }
+ return eventObj.defaultPrevented;
+};
+
+/**
+ * Indicates whether there is at least one listener for the specified event type.
+ * @method hasEventListener
+ * @param {String} type The string type of the event.
+ * @return {Boolean} Returns true if there is at least one listener for the specified event.
+ **/
+p.hasEventListener = function (type) {
+ var listeners = this._listeners, captureListeners = this._captureListeners;
+ return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type]));
+};
+
+/**
+ * Indicates whether there is at least one listener for the specified event type on this object or any of its
+ * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the
+ * specified type is dispatched from this object, it will trigger at least one listener.
+ *
+ * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire
+ * event flow for a listener, not just this object.
+ * @method willTrigger
+ * @param {String} type The string type of the event.
+ * @return {Boolean} Returns `true` if there is at least one listener for the specified event.
+ **/
+p.willTrigger = function (type) {
+ var o = this;
+ while (o) {
+ if (o.hasEventListener(type)) {
+ return true;
+ }
+ o = o.parent;
+ }
+ return false;
+};
+
+/**
+ * @method toString
+ * @return {String} a string representation of the instance.
+ **/
+p.toString = function () {
+ return "[EventDispatcher]";
+};
+
+
+// private methods:
+/**
+ * @method _dispatchEvent
+ * @param {Object | String | Event} eventObj
+ * @param {Object} eventPhase
+ * @protected
+ **/
+p._dispatchEvent = function (eventObj, eventPhase) {
+ var l, listeners = (eventPhase == 1) ? this._captureListeners : this._listeners;
+ if (eventObj && listeners) {
+ var arr = listeners[eventObj.type];
+ if (!arr || !(l = arr.length)) {
+ return;
+ }
+ try {
+ eventObj.currentTarget = this;
+ } catch (e) {
+ }
+ try {
+ eventObj.eventPhase = eventPhase;
+ } catch (e) {
+ }
+ eventObj.removed = false;
+
+ arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
+ for (var i = 0; i < l && !eventObj.immediatePropagationStopped; i++) {
+ var o = arr[i];
+ if (o.handleEvent) {
+ o.handleEvent(eventObj);
+ }
+ else {
+ o(eventObj);
+ }
+ if (eventObj.removed) {
+ this.off(eventObj.type, o, eventPhase == 1);
+ eventObj.removed = false;
+ }
+ }
+ }
+};
+
+
+module.exports = EventDispatcher = EventDispatcher;
+
+},{"./Event":2}],4:[function(_dereq_,module,exports){
+/*
+* extend
+* Visit http://createjs.com/ for documentation, updates and examples.
+*
+* Copyright (c) 2010 gskinner.com, inc.
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following
+* conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * @module CreateJS
+ */
+
+/**
+ * @class Utility Methods
+ */
+
+/**
+ * Sets up the prototype chain and constructor property for a new class.
+ *
+ * This should be called right after creating the class constructor.
+ *
+ * function MySubClass() {}
+ * createjs.extend(MySubClass, MySuperClass);
+ * ClassB.prototype.doSomething = function() { }
+ *
+ * var foo = new MySubClass();
+ * console.log(foo instanceof MySuperClass); // true
+ * console.log(foo.prototype.constructor === MySubClass); // true
+ *
+ * @method extend
+ * @param {Function} subclass The subclass.
+ * @param {Function} superclass The superclass to extend.
+ * @return {Function} Returns the subclass's new prototype.
+ */
+module.exports = function(subclass, superclass) {
+ "use strict";
+
+ function o() { this.constructor = subclass; }
+ o.prototype = superclass.prototype;
+ return (subclass.prototype = new o());
+};
+
+},{}],5:[function(_dereq_,module,exports){
+/*
+* promote
+* Visit http://createjs.com/ for documentation, updates and examples.
+*
+* Copyright (c) 2010 gskinner.com, inc.
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following
+* conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * @module CreateJS
+ */
+
+/**
+ * @class Utility Methods
+ */
+
+/**
+ * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`.
+ * It is recommended to use the super class's name as the prefix.
+ * An alias to the super class's constructor is always added in the format `prefix_constructor`.
+ * This allows the subclass to call super class methods without using `function.call`, providing better performance.
+ *
+ * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")`
+ * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the
+ * prototype of `MySubClass` as `MySuperClass_draw`.
+ *
+ * This should be called after the class's prototype is fully defined.
+ *
+ * function ClassA(name) {
+ * this.name = name;
+ * }
+ * ClassA.prototype.greet = function() {
+ * return "Hello "+this.name;
+ * }
+ *
+ * function ClassB(name, punctuation) {
+ * this.ClassA_constructor(name);
+ * this.punctuation = punctuation;
+ * }
+ * createjs.extend(ClassB, ClassA);
+ * ClassB.prototype.greet = function() {
+ * return this.ClassA_greet()+this.punctuation;
+ * }
+ * createjs.promote(ClassB, "ClassA");
+ *
+ * var foo = new ClassB("World", "!?!");
+ * console.log(foo.greet()); // Hello World!?!
+ *
+ * @method promote
+ * @param {Function} subclass The class to promote super class methods on.
+ * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass.
+ * @return {Function} Returns the subclass.
+ */
+module.exports = function(subclass, prefix) {
+ "use strict";
+
+ var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__;
+ if (supP) {
+ subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable
+ for (var n in supP) {
+ if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; }
+ }
+ }
+ return subclass;
+};
+
+},{}],6:[function(_dereq_,module,exports){
+/*
+ * Proxy
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ * Copyright (c) 2010 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module CreateJS
+ */
+
+// namespace:
+
+/**
+ * Various utilities that the CreateJS Suite uses. Utilities are created as separate files, and will be available on the
+ * createjs namespace directly.
+ *
+ * Example
+ *
+ * myObject.addEventListener("change", createjs.proxy(myMethod, scope));
+ *
+ * @class Utility Methods
+ * @main Utility Methods
+ */
+
+
+/**
+ * A function proxy for methods. By default, JavaScript methods do not maintain scope, so passing a method as a
+ * callback will result in the method getting called in the scope of the caller. Using a proxy ensures that the
+ * method gets called in the correct scope.
+ *
+ * Additional arguments can be passed that will be applied to the function when it is called.
+ *
+ * Example
+ *
+ * myObject.addEventListener("event", createjs.proxy(myHandler, this, arg1, arg2));
+ *
+ * function myHandler(arg1, arg2) {
+ * // This gets called when myObject.myCallback is executed.
+ * }
+ *
+ * @method proxy
+ * @param {Function} method The function to call
+ * @param {Object} scope The scope to call the method name on
+ * @param {mixed} [arg] * Arguments that are appended to the callback for additional params.
+ * @public
+ * @static
+ */
+module.exports = function (method, scope) {
+ var aArgs = Array.prototype.slice.call(arguments, 2);
+ return function () {
+ return method.apply(scope, Array.prototype.slice.call(arguments, 0).concat(aArgs));
+ };
+}
+},{}],7:[function(_dereq_,module,exports){
+/*
+ * LoadQueue
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * PreloadJS provides a consistent way to preload content for use in HTML applications. Preloading can be done using
+ * HTML tags, as well as XHR.
+ *
+ * By default, PreloadJS will try and load content using XHR, since it provides better support for progress and
+ * completion events, however due to cross-domain issues, it may still be preferable to use tag-based loading
+ * instead. Note that some content requires XHR to work (plain text, web audio), and some requires tags (HTML audio).
+ * Note this is handled automatically where possible.
+ *
+ * PreloadJS currently supports all modern browsers, and we have done our best to include support for most older
+ * browsers. If you find an issue with any specific OS/browser combination, please visit http://community.createjs.com/
+ * and report it.
+ *
+ * Getting Started
+ * To get started, check out the {{#crossLink "LoadQueue"}}{{/crossLink}} class, which includes a quick overview of how
+ * to load files and process results.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.installPlugin(createjs.Sound);
+ * queue.on("complete", handleComplete, this);
+ * queue.loadFile({id:"sound", src:"http://path/to/sound.mp3"});
+ * queue.loadManifest([
+ * {id: "myImage", src:"path/to/myImage.jpg"}
+ * ]);
+ * function handleComplete() {
+ * createjs.Sound.play("sound");
+ * var image = queue.getResult("myImage");
+ * document.body.appendChild(image);
+ * }
+ *
+ * Important note on plugins: Plugins must be installed before items are added to the queue, otherwise
+ * they will not be processed, even if the load has not actually kicked off yet. Plugin functionality is handled when
+ * the items are added to the LoadQueue.
+ *
+ * Browser Support
+ * PreloadJS is partially supported in all browsers, and fully supported in all modern browsers. Known exceptions:
+ * - XHR loading of any content will not work in many older browsers (See a matrix here: http://caniuse.com/xhr2).
+ * In many cases, you can fall back on tag loading (images, audio, CSS, scripts, and SVG). Text and
+ * WebAudio will only work with XHR.
+ * - Some formats have poor support for complete events in IE 6, 7, and 8 (SVG, tag loading of scripts, XML/JSON)
+ * - Opera has poor support for SVG loading with XHR
+ * - CSS loading in Android and Safari will not work with tags (currently, a workaround is in progress)
+ * - Local loading is not permitted with XHR, which is required by some file formats. When testing local content
+ * use either a local server, or enable tag loading, which is supported for most formats. See {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}}
+ * for more information.
+ *
+ *
+ * Cross-domain Loading
+ * Most content types can be loaded cross-domain, as long as the server supports CORS. PreloadJS also has internal
+ * support for images served from a CORS-enabled server, via the `crossOrigin` argument on the {{#crossLink "LoadQueue"}}{{/crossLink}}
+ * constructor. If set to a string value (such as "Anonymous"), the "crossOrigin" property of images generated by
+ * PreloadJS is set to that value. Please note that setting a `crossOrigin` value on an image that is served from a
+ * server without CORS will cause other errors. For more info on CORS, visit https://en.wikipedia.org/wiki/Cross-origin_resource_sharing.
+ *
+ * @module PreloadJS
+ * @main PreloadJS
+ */
+
+// namespace:
+
+
+/*
+ TODO: WINDOWS ISSUES
+ * No error for HTML audio in IE 678
+ * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR
+ * No script complete handler in IE 67 TAGS (XHR is fine)
+ * No XML/JSON in IE6 TAGS
+ * Need to hide loading SVG in Opera TAGS
+ * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking)
+ * SVG no load or failure in Opera XHR
+ * Reported issues with IE7/8
+ */
+
+// constructor
+/**
+ * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either
+ * a single file, or queue of files.
+ *
+ * Creating a Queue
+ * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR
+ * argument to false.
+ *
+ * var queue = new createjs.LoadQueue(true);
+ *
+ * Listening for Events
+ * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}}
+ * lets you add as many listeners as you want for events. You can subscribe to the following events:
+ * - {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all
+ * files
+ * - {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with
+ * any file.
+ * - {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has
+ * changed.
+ * - {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
+ * - {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note
+ * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
+ *
+ *
+ * queue.on("fileload", handleFileLoad, this);
+ * queue.on("complete", handleComplete, this);
+ *
+ * Adding files and manifests
+ * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a
+ * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are
+ * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you
+ * like.
+ *
+ * queue.loadFile("filePath/file.jpg");
+ * queue.loadFile({id:"image", src:"filePath/file.jpg"});
+ * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]);
+ *
+ * // Use an external manifest
+ * queue.loadManifest("path/to/manifest.json");
+ * queue.loadManifest({src:"manifest.json", type:"manifest"});
+ *
+ * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not
+ * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin
+ * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a
+ * `loadNow` argument of `true`.
+ *
+ * queue.load();
+ *
+ * File Types
+ * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS
+ * should handle the majority of standard file and url formats, and works with common file extensions. If you have
+ * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a
+ * type
property with any manifest item.
+ *
+ * queue.loadFile({src:"path/to/myFile.mp3x", type:AbstractLoader.SOUND});
+ *
+ * // Note that PreloadJS will not read a file extension from the query string
+ * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:AbstractLoader.IMAGE});
+ *
+ * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
+ *
+ * - {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
+ * - {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files
+ * - {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats
+ * - {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
+ * - {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data
+ * - {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
+ * - {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see
+ * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
+ * - {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats
+ * - {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This
+ * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
+ * - {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files
+ * - {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only
+ * - {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}: Video objects
+ * - {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data
+ *
+ *
+ * Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better
+ * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but
+ * are deprecated.
+ *
+ * Handling Results
+ * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is
+ * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a
+ * formatted object that can be used immediately, including:
+ *
+ * - Binary: The binary loaded result
+ * - CSS: A <link /> tag
+ * - Image: An <img /> tag
+ * - JavaScript: A <script /> tag
+ * - JSON/JSONP: A formatted JavaScript Object
+ * - Manifest: A JavaScript object.
+ *
- Sound: An <audio /> tag
+ *
- SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images.
+ *
- SVG: An <object /> tag
+ * - Text: Raw text
+ * - Video: A Video DOM node
+ * - XML: An XML DOM node
+ *
+ *
+ * function handleFileLoad(event) {
+ * var item = event.item; // A reference to the item that was passed in to the LoadQueue
+ * var type = item.type;
+ *
+ * // Add any images to the page body.
+ * if (type == createjs.LoadQueue.IMAGE) {
+ * document.body.appendChild(event.result);
+ * }
+ * }
+ *
+ * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up
+ * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the
+ * "src" or file path can be used instead, including the `path` defined by a manifest, but not including
+ * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content.
+ *
+ * var image = queue.getResult("image");
+ * document.body.appendChild(image);
+ *
+ * Raw loaded content can be accessed using the rawResult
property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
+ * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
+ * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
+ *
+ * var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
+ *
+ * Plugins
+ * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio,
+ * make sure to install the SoundJS Sound class, which will help load HTML audio,
+ * Flash audio, and WebAudio files. This should be installed before loading any audio files.
+ *
+ * queue.installPlugin(createjs.Sound);
+ *
+ * Known Browser Issues
+ *
+ * - Browsers without audio support can not load audio files.
+ * - Safari on Mac OS X can only play HTML audio if QuickTime is installed
+ * - HTML Audio tags will only download until their
canPlayThrough
event is fired. Browsers other
+ * than Chrome will continue to download in the background.
+ * - When loading scripts using tags, they are automatically added to the document.
+ * - Scripts loaded via XHR may not be properly inspectable with browser tools.
+ * - IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require
+ * XHR to work.
+ * - Content loaded via tags will not show progress, and will continue to download in the background when
+ * canceled, although no events will be dispatched.
+ *
+ *
+ * @class LoadQueue
+ * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP
+ * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR
+ * when necessary.
+ * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue
+ * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../`
+ * will not receive a base path.
+ * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To
+ * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any
+ * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin
+ * parameter is deprecated. Use LoadItem.crossOrigin instead
+ *
+ * @constructor
+ * @extends AbstractLoader
+ */
+
+var ImageLoader = _dereq_('./loaders/ImageLoader');
+var extend = _dereq_('../createjs/utils/extend');
+var promote = _dereq_('../createjs/utils/promote');
+var AbstractLoader = _dereq_('./loaders/AbstractLoader');
+var Event = _dereq_('../createjs/events/Event');
+var ErrorEvent = _dereq_('../createjs/events/ErrorEvent');
+var RequestUtils = _dereq_('./utils/RequestUtils');
+var LoadItem = _dereq_('./data/LoadItem');
+
+function LoadQueue(preferXHR, basePath, crossOrigin) {
+ this.AbstractLoader_constructor();
+
+ /**
+ * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}.
+ * @property _plugins
+ * @type {Array}
+ * @private
+ * @since 0.6.1
+ */
+ this._plugins = [];
+
+ /**
+ * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the
+ * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
+ * method for more information.
+ * @property _typeCallbacks
+ * @type {Object}
+ * @private
+ */
+ this._typeCallbacks = {};
+
+ /**
+ * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the
+ * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
+ * method for more information.
+ * @property _extensionCallbacks
+ * @type {null}
+ * @private
+ */
+ this._extensionCallbacks = {};
+
+ /**
+ * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and
+ * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed.
+ * @property next
+ * @type {LoadQueue}
+ * @default null
+ */
+ this.next = null;
+
+ /**
+ * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head
+ * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas
+ * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order
+ * specified.
+ *
+ * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}}
+ * property on the load item, or by ensuring that only one connection can be open at a time using
+ * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property
+ * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the
+ * `maintainScriptOrder` to `false` during a load will not change items already in a queue.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(3); // Set a higher number to load multiple items at once
+ * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order
+ * queue.loadManifest([
+ * "script1.js",
+ * "script2.js",
+ * "image.png", // Load any time
+ * {src: "image2.png", maintainOrder: true} // Will wait for script2.js
+ * "image3.png",
+ * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR)
+ * ]);
+ *
+ * @property maintainScriptOrder
+ * @type {Boolean}
+ * @default true
+ */
+ this.maintainScriptOrder = true;
+
+ /**
+ * Determines if the LoadQueue will stop processing the current queue when an error is encountered.
+ * @property stopOnError
+ * @type {Boolean}
+ * @default false
+ */
+ this.stopOnError = false;
+
+ /**
+ * The number of maximum open connections that a loadQueue tries to maintain. Please see
+ * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information.
+ * @property _maxConnections
+ * @type {Number}
+ * @default 1
+ * @private
+ */
+ this._maxConnections = 1;
+
+ /**
+ * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the
+ * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can
+ * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is
+ * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the
+ * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of
+ * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}.
+ *
+ * Loaders can be removed from PreloadJS by simply not including them.
+ *
+ * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list
+ * so that they are checked first.
+ * @property _availableLoaders
+ * @type {Array}
+ * @private
+ * @since 0.6.0
+ */
+ this._availableLoaders = [
+ ImageLoader
+ /*,
+ createjs.JavaScriptLoader,
+ createjs.CSSLoader,
+ createjs.JSONLoader,
+ createjs.JSONPLoader,
+ createjs.SoundLoader,
+ createjs.ManifestLoader,
+ createjs.SpriteSheetLoader,
+ createjs.XMLLoader,
+ createjs.SVGLoader,
+ createjs.BinaryLoader,
+ createjs.VideoLoader,
+ createjs.TextLoader
+ */
+ ];
+
+ /**
+ * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}.
+ * @property _defaultLoaderLength
+ * @type {Number}
+ * @private
+ * @since 0.6.0
+ */
+ this._defaultLoaderLength = this._availableLoaders.length;
+
+ this.init(preferXHR, basePath, crossOrigin);
+}
+
+var p = extend(LoadQueue, AbstractLoader);
+var s = LoadQueue;
+
+/**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+// p.initialize = function() {}; // searchable for devs wondering where it is.
+
+/**
+ * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue.
+ * @method init
+ * @param preferXHR
+ * @param basePath
+ * @param crossOrigin
+ * @private
+ */
+p.init = function (preferXHR, basePath, crossOrigin) {
+
+ // public properties
+ /**
+ * @property useXHR
+ * @type {Boolean}
+ * @readonly
+ * @default true
+ * @deprecated Use preferXHR instead.
+ */
+ this.useXHR = true;
+
+ /**
+ * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR
+ * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR,
+ * and plain text can not be loaded with tags, so it will default the the correct type instead of using the
+ * user-defined type.
+ * @type {Boolean}
+ * @default true
+ * @since 0.6.0
+ */
+ this.preferXHR = true; //TODO: Get/Set
+ this._preferXHR = true;
+ this.setPreferXHR(preferXHR);
+
+ // protected properties
+ /**
+ * Whether the queue is currently paused or not.
+ * @property _paused
+ * @type {boolean}
+ * @private
+ */
+ this._paused = false;
+
+ /**
+ * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The
+ * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such
+ * as `http://`, or a relative path such as `../`.
+ * @property _basePath
+ * @type {String}
+ * @private
+ * @since 0.3.1
+ */
+ this._basePath = basePath;
+
+ /**
+ * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded
+ * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by
+ * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues,
+ * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are ""
+ * and "Anonymous".
+ * @property _crossOrigin
+ * @type {String}
+ * @default ""
+ * @private
+ * @since 0.4.1
+ */
+ this._crossOrigin = crossOrigin;
+
+ /**
+ * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first
+ * file is requested.
+ * @property _loadStartWasDispatched
+ * @type {Boolean}
+ * @default false
+ * @private
+ */
+ this._loadStartWasDispatched = false;
+
+ /**
+ * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when
+ * using a script tag to do preloading.
+ * @property _currentlyLoadingScript
+ * @type {Boolean}
+ * @private
+ */
+ this._currentlyLoadingScript = null;
+
+ /**
+ * An array containing the currently downloading files.
+ * @property _currentLoads
+ * @type {Array}
+ * @private
+ */
+ this._currentLoads = [];
+
+ /**
+ * An array containing the queued items that have not yet started downloading.
+ * @property _loadQueue
+ * @type {Array}
+ * @private
+ */
+ this._loadQueue = [];
+
+ /**
+ * An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
+ * @property _loadQueueBackup
+ * @type {Array}
+ * @private
+ */
+ this._loadQueueBackup = [];
+
+ /**
+ * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}}
+ * id.
+ * @property _loadItemsById
+ * @type {Object}
+ * @private
+ */
+ this._loadItemsById = {};
+
+ /**
+ * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * source.
+ * @property _loadItemsBySrc
+ * @type {Object}
+ * @private
+ */
+ this._loadItemsBySrc = {};
+
+ /**
+ * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @property _loadedResults
+ * @type {Object}
+ * @private
+ */
+ this._loadedResults = {};
+
+ /**
+ * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @property _loadedRawResults
+ * @type {Object}
+ * @private
+ */
+ this._loadedRawResults = {};
+
+ /**
+ * The number of items that have been requested. This helps manage an overall progress without knowing how large
+ * the files are before they are downloaded. This does not include items inside of loaders such as the
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _numItems
+ * @type {Number}
+ * @default 0
+ * @private
+ */
+ this._numItems = 0;
+
+ /**
+ * The number of items that have completed loaded. This helps manage an overall progress without knowing how large
+ * the files are before they are downloaded.
+ * @property _numItemsLoaded
+ * @type {Number}
+ * @default 0
+ * @private
+ */
+ this._numItemsLoaded = 0;
+
+ /**
+ * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right
+ * order.
+ * @property _scriptOrder
+ * @type {Array}
+ * @private
+ */
+ this._scriptOrder = [];
+
+ /**
+ * A list of scripts that have been loaded. Items are added to this list as null
when they are
+ * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true
+ * once they are complete and have been dispatched.
+ * @property _loadedScripts
+ * @type {Array}
+ * @private
+ */
+ this._loadedScripts = [];
+
+ /**
+ * The last progress amount. This is used to suppress duplicate progress events.
+ * @property _lastProgress
+ * @type {Number}
+ * @private
+ * @since 0.6.0
+ */
+ this._lastProgress = NaN;
+
+};
+
+// static properties
+/**
+ * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event is dispatched if the timeout is reached before any data is received.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000
+ * @static
+ * @since 0.4.1
+ * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
+ */
+s.loadTimeout = 8000;
+
+/**
+ * The time in milliseconds to assume a load has failed.
+ * @property LOAD_TIMEOUT
+ * @type {Number}
+ * @default 0
+ * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
+ */
+s.LOAD_TIMEOUT = 0;
+
+// Preload Types
+/**
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
+ */
+s.BINARY = AbstractLoader.BINARY;
+
+/**
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+s.CSS = AbstractLoader.CSS;
+
+/**
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+s.IMAGE = AbstractLoader.IMAGE;
+
+/**
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.JAVASCRIPT = AbstractLoader.JAVASCRIPT;
+
+/**
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
+ */
+s.JSON = AbstractLoader.JSON;
+
+/**
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
+ */
+s.JSONP = AbstractLoader.JSONP;
+
+/**
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.4.1
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
+ */
+s.MANIFEST = AbstractLoader.MANIFEST;
+
+/**
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.SOUND = AbstractLoader.SOUND;
+
+/**
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.VIDEO = AbstractLoader.VIDEO;
+
+/**
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
+ */
+s.SVG = AbstractLoader.SVG;
+
+/**
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
+ */
+s.TEXT = AbstractLoader.TEXT;
+
+/**
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
+ */
+s.XML = AbstractLoader.XML;
+
+/**
+ * @property POST
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
+ */
+s.POST = AbstractLoader.POST;
+
+/**
+ * @property GET
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
+ */
+s.GET = AbstractLoader.GET;
+
+// events
+/**
+ * This event is fired when an individual file has loaded, and been processed.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.3.0
+ */
+
+/**
+ * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
+ * @event fileprogress
+ * @since 0.3.0
+ */
+
+/**
+ * This event is fired when an individual file starts to load.
+ * @event filestart
+ * @param {Object} The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a property.
+ */
+
+/**
+ * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from
+ * a LoadQueue instance.
+ * @event initialize
+ * @private
+ */
+
+// public methods
+/**
+ * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
+ * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
+ * once, and will be prepended to the list of available loaders.
+ * @method registerLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
+ * @since 0.6.0
+ */
+p.registerLoader = function (loader) {
+ if (!loader || !loader.canLoadItem) {
+ throw new Error("loader is of an incorrect type.");
+ } else if (this._availableLoaders.indexOf(loader) != -1) {
+ throw new Error("loader already exists."); //LM: Maybe just silently fail here
+ }
+
+ this._availableLoaders.unshift(loader);
+};
+
+/**
+ * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
+ * unregistered, the default loaders will always be available.
+ * @method unregisterLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
+ */
+p.unregisterLoader = function (loader) {
+ var idx = this._availableLoaders.indexOf(loader);
+ if (idx != -1 && idx < this._defaultLoaderLength - 1) {
+ this._availableLoaders.splice(idx, 1);
+ }
+};
+
+/**
+ * @method setUseXHR
+ * @param {Boolean} value The new useXHR value to set.
+ * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
+ * the provided value argument was true.
+ * @since 0.3.0
+ * @deprecated use the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property, or the
+ * {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} method instead.
+ */
+p.setUseXHR = function (value) {
+ return this.setPreferXHR(value);
+};
+
+/**
+ * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
+ * fail, or be ignored depending on the browser's capabilities and the load type.
+ * @method setPreferXHR
+ * @param {Boolean} value
+ * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
+ * @since 0.6.0
+ */
+p.setPreferXHR = function (value) {
+ // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
+ //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
+ this.preferXHR = (value != false && window.XMLHttpRequest != null);
+ return this.preferXHR;
+};
+
+/**
+ * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
+ * content, and allows the queue to be used again.
+ * @method removeAll
+ * @since 0.3.0
+ */
+p.removeAll = function () {
+ this.remove();
+};
+
+/**
+ * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
+ * This also removes internal references to loaded item(s).
+ *
+ * Example
+ *
+ * queue.loadManifest([
+ * {src:"test.png", id:"png"},
+ * {src:"test.jpg", id:"jpg"},
+ * {src:"test.mp3", id:"mp3"}
+ * ]);
+ * queue.remove("png"); // Single item by ID
+ * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
+ * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
+ *
+ * @method remove
+ * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
+ * items, or multiple items as arguments.
+ * @since 0.3.0
+ */
+p.remove = function (idsOrUrls) {
+ var args = null;
+
+ if (idsOrUrls && !Array.isArray(idsOrUrls)) {
+ args = [idsOrUrls];
+ } else if (idsOrUrls) {
+ args = idsOrUrls;
+ } else if (arguments.length > 0) {
+ return;
+ }
+
+ var itemsWereRemoved = false;
+
+ // Destroy everything
+ if (!args) {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
+ this.init(this.preferXHR, this._basePath);
+
+ // Remove specific items
+ } else {
+ while (args.length) {
+ var item = args.pop();
+ var r = this.getResult(item);
+
+ //Remove from the main load Queue
+ for (i = this._loadQueue.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueue[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueue.splice(i, 1)[0].cancel();
+ break;
+ }
+ }
+
+ //Remove from the backup queue
+ for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueueBackup[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueueBackup.splice(i, 1)[0].cancel();
+ break;
+ }
+ }
+
+ if (r) {
+ this._disposeItem(this.getItem(item));
+ } else {
+ for (var i = this._currentLoads.length - 1; i >= 0; i--) {
+ var loadItem = this._currentLoads[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._currentLoads.splice(i, 1)[0].cancel();
+ itemsWereRemoved = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // If this was called during a load, try to load the next item.
+ if (itemsWereRemoved) {
+ this._loadNext();
+ }
+ }
+};
+
+/**
+ * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
+ * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
+ * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
+ * @method reset
+ * @since 0.3.0
+ */
+p.reset = function () {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
+
+ //Reset the queue to its start state
+ var a = [];
+ for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
+ a.push(this._loadQueueBackup[i].getItem());
+ }
+
+ this.loadManifest(a, false);
+};
+
+/**
+ * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
+ * Currently, only one plugin can exist per type/extension.
+ *
+ * When a plugin is installed, a getPreloadHandlers()
method will be called on it. For more information
+ * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
+ * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
+ *
+ * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
+ * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
+ * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
+ * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
+ * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
+ * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
+ *
+ * @method installPlugin
+ * @param {Function} plugin The plugin class to install.
+ */
+p.installPlugin = function (plugin) {
+ if (plugin == null) {
+ return;
+ }
+
+ if (plugin.getPreloadHandlers != null) {
+ this._plugins.push(plugin);
+ var map = plugin.getPreloadHandlers();
+ map.scope = plugin;
+
+ if (map.types != null) {
+ for (var i = 0, l = map.types.length; i < l; i++) {
+ this._typeCallbacks[map.types[i]] = map;
+ }
+ }
+
+ if (map.extensions != null) {
+ for (i = 0, l = map.extensions.length; i < l; i++) {
+ this._extensionCallbacks[map.extensions[i]] = map;
+ }
+ }
+ }
+};
+
+/**
+ * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
+ * number of open connections, so any additional connections may remain in a pending state until the browser
+ * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
+ * is `true`, only one script is loaded at a time due to browser limitations.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(10); // Allow 10 concurrent loads
+ *
+ * @method setMaxConnections
+ * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
+ * is open at any time.
+ */
+p.setMaxConnections = function (value) {
+ this._maxConnections = value;
+ if (!this._paused && this._loadQueue.length > 0) {
+ this._loadNext();
+ }
+};
+
+/**
+ * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method.
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadFile
+ * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+p.loadFile = function (file, loadNow, basePath) {
+ if (file == null) {
+ var event = new ErrorEvent("PRELOAD_NO_FILE");
+ this._sendError(event);
+ return;
+ }
+ this._addItem(file, null, basePath);
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+};
+
+/**
+ * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
+ * The files in the manifest are requested in the same order, but may complete in a different order if the max
+ * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
+ * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
+ * default).
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadManifest
+ * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
+ * manifests:
+ *
+ * - A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
+ * which defines the list of files to load, and can optionally contain a "path" property, which will be
+ * prepended to each file in the list.
+ * - An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
+ * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
+ * and can optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An object which contains a "manifest" property, which defines the list of files to load, and can
+ * optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An Array of files to load.
+ *
+ *
+ * Each "file" in a manifest can be either:
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+p.loadManifest = function (manifest, loadNow, basePath) {
+ var fileList = null;
+ var path = null;
+
+ // Array-based list of items
+ if (Array.isArray(manifest)) {
+ if (manifest.length == 0) {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_EMPTY");
+ this._sendError(event);
+ return;
+ }
+ fileList = manifest;
+
+ // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
+ } else if (typeof(manifest) === "string") {
+ fileList = [
+ {
+ src: manifest,
+ type: s.MANIFEST
+ }
+ ];
+
+ } else if (typeof(manifest) == "object") {
+
+ // An object that defines a manifest path
+ if (manifest.src !== undefined) {
+ if (manifest.type == null) {
+ manifest.type = s.MANIFEST;
+ } else if (manifest.type != s.MANIFEST) {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_TYPE");
+ this._sendError(event);
+ }
+ fileList = [manifest];
+
+ // An object that defines a manifest
+ } else if (manifest.manifest !== undefined) {
+ fileList = manifest.manifest;
+ path = manifest.path;
+ }
+
+ // Unsupported. This will throw an error.
+ } else {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_NULL");
+ this._sendError(event);
+ return;
+ }
+
+ for (var i = 0, l = fileList.length; i < l; i++) {
+ this._addItem(fileList[i], path, basePath);
+ }
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+
+};
+
+/**
+ * Start a LoadQueue that was created, but not automatically started.
+ * @method load
+ */
+p.load = function () {
+ this.setPaused(false);
+};
+
+/**
+ * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
+ * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getItem
+ * @param {String} value The id
or src
of the load item.
+ * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event as the `item` parameter.
+ */
+p.getItem = function (value) {
+ return this._loadItemsById[value] || this._loadItemsBySrc[value];
+};
+
+/**
+ * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
+ * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getResult
+ * @param {String} value The id
or src
of the load item.
+ * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML
+ * DOM.
+ * - A style tag for CSS (<style /> or <link >)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - A binary arraybuffer loaded by XHR
+ * - An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play
+ * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
+ * which can not be used to play audio back.
+ *
+ * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
+ * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+p.getResult = function (value, rawResult) {
+ var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
+ if (item == null) {
+ return null;
+ }
+ var id = item.id;
+ if (rawResult && this._loadedRawResults[id]) {
+ return this._loadedRawResults[id];
+ }
+ return this._loadedResults[id];
+};
+
+/**
+ * Generate an list of items loaded by this queue.
+ * @method getItems
+ * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
+ * and failed load items will also be included.
+ * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
+ * result, and rawResult.
+ * @since 0.6.0
+ */
+p.getItems = function (loaded) {
+ var arr = [];
+ for (var n in this._loadItemsById) {
+ var item = this._loadItemsById[n];
+ var result = this.getResult(n);
+ if (loaded === true && result == null) {
+ continue;
+ }
+ arr.push({
+ item: item,
+ result: result,
+ rawResult: this.getResult(n, true)
+ });
+ }
+ return arr;
+};
+
+/**
+ * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
+ * be processed when active loads complete. LoadQueues are not paused by default.
+ *
+ * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
+ * argument is `false`.
+ * @method setPaused
+ * @param {Boolean} value Whether the queue should be paused or not.
+ */
+p.setPaused = function (value) {
+ this._paused = value;
+ if (!this._paused) {
+ this._loadNext();
+ }
+};
+
+/**
+ * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
+ * starting to download. Note that currently any active loads will remain open, and events may be processed.
+ *
+ * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
+ * @method close
+ */
+p.close = function () {
+ while (this._currentLoads.length) {
+ this._currentLoads.pop().cancel();
+ }
+ this._scriptOrder.length = 0;
+ this._loadedScripts.length = 0;
+ this.loadStartWasDispatched = false;
+ this._itemCount = 0;
+ this._lastProgress = NaN;
+};
+
+// protected methods
+/**
+ * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
+ * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
+ * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
+ * method.
+ * @method _addItem
+ * @param {String|Object} value The item to add to the queue.
+ * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
+ * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
+ * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
+ * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
+ * version.
+ * @private
+ */
+p._addItem = function (value, path, basePath) {
+ var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
+ if (item == null) {
+ return;
+ } // Sometimes plugins or types should be skipped.
+ var loader = this._createLoader(item);
+ if (loader != null) {
+ if ("plugins" in loader) {
+ loader.plugins = this._plugins;
+ }
+ item._loader = loader;
+ this._loadQueue.push(loader);
+ this._loadQueueBackup.push(loader);
+
+ this._numItems++;
+ this._updateProgress();
+
+ // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
+ if ((this.maintainScriptOrder
+ && item.type == LoadQueue.JAVASCRIPT
+ //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
+ )
+ || item.maintainOrder === true) {
+ this._scriptOrder.push(item);
+ this._loadedScripts.push(null);
+ }
+ }
+};
+
+/**
+ * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
+ * item is determined by browser support, requirements based on the file type, and developer settings. For example,
+ * XHR is only used for file types that support it in new browsers.
+ *
+ * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
+ * alter the load item.
+ * @method _createLoadItem
+ * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
+ * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
+ * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
+ * when it is added.
+ * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to
+ * the path argument.
+ * @return {Object} The loader instance that will be used.
+ * @private
+ */
+p._createLoadItem = function (value, path, basePath) {
+ var item = LoadItem.create(value);
+ if (item == null) {
+ return null;
+ }
+
+ var bp = ""; // Store the generated basePath
+ var useBasePath = basePath || this._basePath;
+
+ if (item.src instanceof Object) {
+ if (!item.type) {
+ return null;
+ } // the the src is an object, type is required to pass off to plugin
+ if (path) {
+ bp = path;
+ var pathMatch = RequestUtils.parseURI(path);
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ } else {
+ // Determine Extension, etc.
+ var match = RequestUtils.parseURI(item.src);
+ if (match.extension) {
+ item.ext = match.extension;
+ }
+ if (item.type == null) {
+ item.type = RequestUtils.getTypeByExtension(item.ext);
+ }
+
+ // Inject path & basePath
+ var autoId = item.src;
+ if (!match.absolute && !match.relative) {
+ if (path) {
+ bp = path;
+ var pathMatch = RequestUtils.parseURI(path);
+ autoId = path + autoId;
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ }
+ item.src = bp + item.src;
+ }
+ item.path = bp;
+
+ // If there's no id, set one now.
+ if (item.id === undefined || item.id === null || item.id === "") {
+ item.id = autoId;
+ }
+
+ // Give plugins a chance to modify the loadItem:
+ var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
+ if (customHandler) {
+ // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
+ var result = customHandler.callback.call(customHandler.scope, item, this);
+
+ // The plugin will handle the load, or has canceled it. Ignore it.
+ if (result === false) {
+ return null;
+
+ // Load as normal:
+ } else if (result === true) {
+ // Do Nothing
+
+ // Result is a loader class:
+ } else if (result != null) {
+ item._loader = result;
+ }
+
+ // Update the extension in case the type changed:
+ match = RequestUtils.parseURI(item.src);
+ if (match.extension != null) {
+ item.ext = match.extension;
+ }
+ }
+
+ // Store the item for lookup. This also helps clean-up later.
+ this._loadItemsById[item.id] = item;
+ this._loadItemsBySrc[item.src] = item;
+
+ if (item.crossOrigin == null) {
+ item.crossOrigin = this._crossOrigin;
+ }
+
+ return item;
+};
+
+/**
+ * Create a loader for a load item.
+ * @method _createLoader
+ * @param {Object} item A formatted load item that can be used to generate a loader.
+ * @return {AbstractLoader} A loader that can be used to load content.
+ * @private
+ */
+p._createLoader = function (item) {
+ if (item._loader != null) { // A plugin already specified a loader
+ return item._loader;
+ }
+
+ // Initially, try and use the provided/supported XHR mode:
+ var preferXHR = this.preferXHR;
+
+ for (var i = 0; i < this._availableLoaders.length; i++) {
+ var loader = this._availableLoaders[i];
+ if (loader && loader.canLoadItem(item)) {
+ return new loader(item, preferXHR);
+ }
+ }
+
+ // TODO: Log error (requires createjs.log)
+ return null;
+};
+
+/**
+ * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
+ * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
+ * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
+ * using tags, which have to be loaded one at a time to maintain load order.
+ * @method _loadNext
+ * @private
+ */
+p._loadNext = function () {
+ if (this._paused) {
+ return;
+ }
+
+ // Only dispatch loadstart event when the first file is loaded.
+ if (!this._loadStartWasDispatched) {
+ this._sendLoadStart();
+ this._loadStartWasDispatched = true;
+ }
+
+ // The queue has completed.
+ if (this._numItems == this._numItemsLoaded) {
+ this.loaded = true;
+ this._sendComplete();
+
+ // Load the next queue, if it has been defined.
+ if (this.next && this.next.load) {
+ this.next.load();
+ }
+ } else {
+ this.loaded = false;
+ }
+
+ // Must iterate forwards to load in the right order.
+ for (var i = 0; i < this._loadQueue.length; i++) {
+ if (this._currentLoads.length >= this._maxConnections) {
+ break;
+ }
+ var loader = this._loadQueue[i];
+
+ // Determine if we should be only loading one tag-script at a time:
+ // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
+ if (!this._canStartLoad(loader)) {
+ continue;
+ }
+ this._loadQueue.splice(i, 1);
+ i--;
+ this._loadItem(loader);
+ }
+};
+
+/**
+ * Begin loading an item. Event listeners are not added to the loaders until the load starts.
+ * @method _loadItem
+ * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
+ * @private
+ */
+p._loadItem = function (loader) {
+ loader.on("fileload", this._handleFileLoad, this);
+ loader.on("progress", this._handleProgress, this);
+ loader.on("complete", this._handleFileComplete, this);
+ loader.on("error", this._handleError, this);
+ loader.on("fileerror", this._handleFileError, this);
+ this._currentLoads.push(loader);
+ this._sendFileStart(loader.getItem());
+ loader.load();
+};
+
+/**
+ * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
+ * events.
+ * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
+ * @private
+ * @since 0.6.0
+ */
+p._handleFileLoad = function (event) {
+ event.target = null;
+ this.dispatchEvent(event);
+};
+
+/**
+ * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
+ * loaders like M
+ * @param event
+ * @private
+ */
+p._handleFileError = function (event) {
+ var newEvent = new ErrorEvent("FILE_LOAD_ERROR", null, event.item);
+ this._sendError(newEvent);
+};
+
+/**
+ * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
+ * is set to `true`.
+ * @method _handleError
+ * @param {ErrorEvent} event The error event, containing relevant error information.
+ * @private
+ */
+p._handleError = function (event) {
+ var loader = event.target;
+ this._numItemsLoaded++;
+
+ this._finishOrderedItem(loader, true);
+ this._updateProgress();
+
+ var newEvent = new ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
+ // TODO: Propagate actual error message.
+
+ this._sendError(newEvent);
+
+ if (!this.stopOnError) {
+ this._removeLoadItem(loader);
+ this._cleanLoadItem(loader);
+ this._loadNext();
+ } else {
+ this.setPaused(true);
+ }
+};
+
+/**
+ * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
+ * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
+ * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
+ * @method _handleFileComplete
+ * @param {Event} event The event object from the loader.
+ * @private
+ */
+p._handleFileComplete = function (event) {
+ var loader = event.target;
+ var item = loader.getItem();
+
+ var result = loader.getResult();
+ this._loadedResults[item.id] = result;
+ var rawResult = loader.getResult(true);
+ if (rawResult != null && rawResult !== result) {
+ this._loadedRawResults[item.id] = rawResult;
+ }
+
+ this._saveLoadedItems(loader);
+
+ // Remove the load item
+ this._removeLoadItem(loader);
+
+ if (!this._finishOrderedItem(loader)) {
+ // The item was NOT managed, so process it now
+ this._processFinishedLoad(item, loader);
+ }
+
+ // Clean up the load item
+ this._cleanLoadItem(loader);
+};
+
+/**
+ * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
+ * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
+ * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
+ * methods.
+ * @method _saveLoadedItems
+ * @param {AbstractLoader} loader
+ * @protected
+ * @since 0.6.0
+ */
+p._saveLoadedItems = function (loader) {
+ // TODO: Not sure how to handle this. Would be nice to expose the items.
+ // Loaders may load sub-items. This adds them to this queue
+ var list = loader.getLoadedItems();
+ if (list === null) {
+ return;
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i].item;
+
+ // Store item lookups
+ this._loadItemsBySrc[item.src] = item;
+ this._loadItemsById[item.id] = item;
+
+ // Store loaded content
+ this._loadedResults[item.id] = list[i].result;
+ this._loadedRawResults[item.id] = list[i].rawResult;
+ }
+};
+
+/**
+ * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
+ * so, trigger prior items to trigger as well.
+ * @method _finishOrderedItem
+ * @param {AbstractLoader} loader
+ * @param {Boolean} loadFailed
+ * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
+ * behaviour if it is.
+ * @private
+ */
+p._finishOrderedItem = function (loader, loadFailed) {
+ var item = loader.getItem();
+
+ if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
+ || item.maintainOrder) {
+
+ //TODO: Evaluate removal of the _currentlyLoadingScript
+ if (loader instanceof createjs.JavaScriptLoader) {
+ this._currentlyLoadingScript = false;
+ }
+
+ var index = createjs.indexOf(this._scriptOrder, item);
+ if (index == -1) {
+ return false;
+ } // This loader no longer exists
+ this._loadedScripts[index] = (loadFailed === true) ? true : item;
+
+ this._checkScriptLoadOrder();
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
+ * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
+ * and then when they are processed and dispatched, the value is set to `true`. This method simply
+ * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
+ * dispatched.
+ * @method _checkScriptLoadOrder
+ * @private
+ */
+p._checkScriptLoadOrder = function () {
+ var l = this._loadedScripts.length;
+
+ for (var i = 0; i < l; i++) {
+ var item = this._loadedScripts[i];
+ if (item === null) {
+ break;
+ } // This is still loading. Do not process further.
+ if (item === true) {
+ continue;
+ } // This has completed, and been processed. Move on.
+
+ var loadItem = this._loadedResults[item.id];
+ if (item.type == createjs.LoadQueue.JAVASCRIPT) {
+ // Append script tags to the head automatically.
+ createjs.DomUtils.appendToHead(loadItem);
+ }
+
+ var loader = item._loader;
+ this._processFinishedLoad(item, loader);
+ this._loadedScripts[i] = true;
+ }
+};
+
+/**
+ * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
+ * the next item.
+ * @method _processFinishedLoad
+ * @param {LoadItem|Object} item
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+p._processFinishedLoad = function (item, loader) {
+ this._numItemsLoaded++;
+
+ // Since LoadQueue needs maintain order, we can't append scripts in the loader.
+ // So we do it here instead. Or in _checkScriptLoadOrder();
+ if (!this.maintainScriptOrder && item.type == LoadQueue.JAVASCRIPT) {
+ var tag = loader.getTag();
+ createjs.DomUtils.appendToHead(tag);
+ }
+
+ this._updateProgress();
+ this._sendFileComplete(item, loader);
+ this._loadNext();
+};
+
+/**
+ * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
+ * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before
+ * the script can even be started, since it exist in the DOM while loading.
+ * @method _canStartLoad
+ * @param {AbstractLoader} loader The loader for the item
+ * @return {Boolean} Whether the item can start a load or not.
+ * @private
+ */
+p._canStartLoad = function (loader) {
+ if (!this.maintainScriptOrder || loader.preferXHR) {
+ return true;
+ }
+ var item = loader.getItem();
+ if (item.type != LoadQueue.JAVASCRIPT) {
+ return true;
+ }
+ if (this._currentlyLoadingScript) {
+ return false;
+ }
+
+ var index = this._scriptOrder.indexOf(item);
+ var i = 0;
+ while (i < index) {
+ var checkItem = this._loadedScripts[i];
+ if (checkItem == null) {
+ return false;
+ }
+ i++;
+ }
+ this._currentlyLoadingScript = true;
+ return true;
+};
+
+/**
+ * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
+ * @method _removeLoadItem
+ * @param {AbstractLoader} loader A loader instance to remove.
+ * @private
+ */
+p._removeLoadItem = function (loader) {
+ var l = this._currentLoads.length;
+ for (var i = 0; i < l; i++) {
+ if (this._currentLoads[i] == loader) {
+ this._currentLoads.splice(i, 1);
+ break;
+ }
+ }
+};
+
+/**
+ * Remove unneeded references from a loader.
+ *
+ * @param loader
+ * @private
+ */
+p._cleanLoadItem = function (loader) {
+ var item = loader.getItem();
+ if (item) {
+ delete item._loader;
+ }
+}
+
+/**
+ * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
+ * @method _handleProgress
+ * @param {ProgressEvent} event The progress event from the item.
+ * @private
+ */
+p._handleProgress = function (event) {
+ var loader = event.target;
+ this._sendFileProgress(loader.getItem(), loader.progress);
+ this._updateProgress();
+};
+
+/**
+ * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
+ * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
+ * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
+ * loaded progress on top of the already-loaded items.
+ *
+ * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
+ *
+ * - 5/10 of the items in the queue (50%)
+ * - plus 20% of item 6's slot (2%)
+ * - equals 52%
+ *
+ * @method _updateProgress
+ * @private
+ */
+p._updateProgress = function () {
+ var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
+ var remaining = this._numItems - this._numItemsLoaded;
+ if (remaining > 0) {
+ var chunk = 0;
+ for (var i = 0, l = this._currentLoads.length; i < l; i++) {
+ chunk += this._currentLoads[i].progress;
+ }
+ loaded += (chunk / remaining) * (remaining / this._numItems);
+ }
+
+ if (this._lastProgress != loaded) {
+ this._sendProgress(loaded);
+ this._lastProgress = loaded;
+ }
+};
+
+/**
+ * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
+ * hashes.
+ * @method _disposeItem
+ * @param {LoadItem|Object} item The item that was passed in for preloading.
+ * @private
+ */
+p._disposeItem = function (item) {
+ delete this._loadedResults[item.id];
+ delete this._loadedRawResults[item.id];
+ delete this._loadItemsById[item.id];
+ delete this._loadItemsBySrc[item.src];
+};
+
+/**
+ * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendFileProgress
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @param {Number} progress The amount the item has been loaded (between 0 and 1).
+ * @protected
+ */
+p._sendFileProgress = function (item, progress) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+ if (!this.hasEventListener("fileprogress")) {
+ return;
+ }
+
+ //LM: Rework ProgressEvent to support this?
+ var event = new Event("fileprogress");
+ event.progress = progress;
+ event.loaded = progress;
+ event.total = 1;
+ event.item = item;
+
+ this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
+ * details on the event payload.
+ * @method _sendFileComplete
+ * @param {LoadItemObject} item The item that is being loaded.
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+p._sendFileComplete = function (item, loader) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+
+ var event = new Event("fileload");
+ event.loader = loader;
+ event.item = item;
+ event.result = this._loadedResults[item.id];
+ event.rawResult = this._loadedRawResults[item.id];
+
+ // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
+ if (item.completeHandler) {
+ item.completeHandler(event);
+ }
+
+ this.hasEventListener("fileload") && this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
+ * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
+ * @method _sendFileStart
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @protected
+ */
+p._sendFileStart = function (item) {
+ var event = new Event("filestart");
+ event.item = item;
+ this.hasEventListener("filestart") && this.dispatchEvent(event);
+};
+
+p.toString = function () {
+ return "[PreloadJS LoadQueue]";
+};
+
+var LoadQueue = promote(LoadQueue, "AbstractLoader");
+
+module.exports = LoadQueue;
+},{"../createjs/events/ErrorEvent":1,"../createjs/events/Event":2,"../createjs/utils/extend":4,"../createjs/utils/promote":5,"./data/LoadItem":8,"./loaders/AbstractLoader":10,"./loaders/ImageLoader":11,"./utils/RequestUtils":15}],8:[function(_dereq_,module,exports){
+/*
+ * LoadItem
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+// namespace:
+
+/**
+ * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead,
+ * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A
+ * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the
+ * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}}
+ * @class LoadItem
+ * @constructor
+ * @since 0.6.0
+ */
+function LoadItem() {
+ /**
+ * The source of the file that is being loaded. This property is required. The source can either be a
+ * string (recommended), or an HTML tag.
+ * This can also be an object, but in that case it has to include a type and be handled by a plugin.
+ * @property src
+ * @type {String}
+ * @default null
+ */
+ this.src = null;
+
+ /**
+ * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
+ * be set manually. This is helpful in cases where a file does not have an extension.
+ * @property type
+ * @type {String}
+ * @default null
+ */
+ this.type = null;
+
+ /**
+ * A string identifier which can be used to reference the loaded object. If none is provided, this will be
+ * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
+ * @property id
+ * @type {String}
+ * @default null
+ */
+ this.id = null;
+
+ /**
+ * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
+ * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
+ * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
+ * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
+ * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
+ * @property maintainOrder
+ * @type {Boolean}
+ * @default false
+ */
+ this.maintainOrder = false;
+
+ /**
+ * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
+ * @property callback
+ * @type {String}
+ * @default null
+ */
+ this.callback = null;
+
+ /**
+ * An arbitrary data object, which is included with the loaded object.
+ * @property data
+ * @type {Object}
+ * @default null
+ */
+ this.data = null;
+
+ /**
+ * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
+ * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
+ * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @property method
+ * @type {String}
+ * @default get
+ */
+ this.method = LoadItem.GET;
+
+ /**
+ * An object hash of name/value pairs to send to the server.
+ * @property values
+ * @type {Object}
+ * @default null
+ */
+ this.values = null;
+
+ /**
+ * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
+ * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
+ * default headers by including them in your headers object.
+ * @property headers
+ * @type {Object}
+ * @default null
+ */
+ this.headers = null;
+
+ /**
+ * Enable credentials for XHR requests.
+ * @property withCredentials
+ * @type {Boolean}
+ * @default false
+ */
+ this.withCredentials = false;
+
+ /**
+ * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
+ * based files (json, xml, text, css, js).
+ * @property mimeType
+ * @type {String}
+ * @default null
+ */
+ this.mimeType = null;
+
+ /**
+ * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
+ * @property crossOrigin
+ * @type {boolean}
+ * @default Anonymous
+ */
+ this.crossOrigin = null;
+
+ /**
+ * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000 (8 seconds)
+ */
+ this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+};
+
+var p = LoadItem.prototype = {};
+var s = LoadItem;
+
+/**
+ * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property LOAD_TIMEOUT_DEFAULT
+ * @type {number}
+ * @static
+ */
+s.LOAD_TIMEOUT_DEFAULT = 8000;
+
+/**
+ * Create a LoadItem.
+ *
+ * - String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
+ * - LoadItem instances are returned as-is
+ * - Objects are returned with any needed properties added
+ *
+ * @method create
+ * @param {LoadItem|String|Object} value The load item value
+ * @returns {LoadItem|Object}
+ * @static
+ */
+s.create = function (value) {
+ if (typeof value == "string") {
+ var item = new LoadItem();
+ item.src = value;
+ return item;
+ } else if (value instanceof s) {
+ return value;
+ } else if (value instanceof Object && value.src) {
+ if (value.loadTimeout == null) {
+ value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+ }
+ return value;
+ } else {
+ throw new Error("Type not recognized.");
+ }
+};
+
+/**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * Example
+ *
+ * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
+ * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
+ */
+p.set = function (props) {
+ for (var n in props) {
+ this[n] = props[n];
+ }
+ return this;
+};
+
+var LoadItem = s;
+module.exports = LoadItem;
+
+},{}],9:[function(_dereq_,module,exports){
+/*
+ * ProgressEvent
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var promote = _dereq_('../../createjs/utils/promote');
+var extend = _dereq_('../../createjs/utils/extend');
+var Event = _dereq_('../../createjs/events/Event');
+
+// constructor
+/**
+ * A CreateJS {{#crossLink "Event"}}{{/crossLink}} that is dispatched when progress changes.
+ * @class ProgressEvent
+ * @param {Number} loaded The amount that has been loaded. This can be any number relative to the total.
+ * @param {Number} [total=1] The total amount that will load. This will default to 1, so if the `loaded` value is
+ * a percentage (between 0 and 1), it can be omitted.
+ * @todo Consider having this event be a "fileprogress" event as well
+ * @constructor
+ */
+function ProgressEvent(loaded, total) {
+ this.Event_constructor("progress");
+
+ /**
+ * The amount that has been loaded (out of a total amount)
+ * @property loaded
+ * @type {Number}
+ */
+ this.loaded = loaded;
+
+ /**
+ * The total "size" of the load.
+ * @property total
+ * @type {Number}
+ * @default 1
+ */
+ this.total = (total == null) ? 1 : total;
+
+ /**
+ * The percentage (out of 1) that the load has been completed. This is calculated using `loaded/total`.
+ * @property progress
+ * @type {Number}
+ * @default 0
+ */
+ this.progress = (total == 0) ? 0 : this.loaded / this.total;
+};
+
+var p = extend(ProgressEvent, Event);
+
+/**
+ * Returns a clone of the ProgressEvent instance.
+ * @method clone
+ * @return {ProgressEvent} a clone of the Event instance.
+ **/
+p.clone = function () {
+ return new ProgressEvent(this.loaded, this.total);
+};
+
+var ProgressEvent = promote(ProgressEvent, "Event");
+module.exports = ProgressEvent;
+
+},{"../../createjs/events/Event":2,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5}],10:[function(_dereq_,module,exports){
+/*
+ * AbstractLoader
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var EventDispatcher = _dereq_('../../createjs/events/EventDispatcher');
+var LoadItem = _dereq_('../data/LoadItem');
+var Event = _dereq_('../../createjs/events/Event');
+var ErrorEvent = _dereq_('../../createjs/events/ErrorEvent');
+var ProgressEvent = _dereq_('../events/ProgressEvent');
+var RequestUtils = _dereq_('../utils/RequestUtils');
+var TagRequest = _dereq_('../net/TagRequest');
+var XHRRequest = _dereq_('../net/XHRRequest');
+var proxy = _dereq_('../../createjs/utils/proxy');
+var promote = _dereq_('../../createjs/utils/promote');
+var extend = _dereq_('../../createjs/utils/extend');
+
+// namespace:
+// constructor
+/**
+ * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
+ * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
+ * @class AbstractLoader
+ * @param {LoadItem|object|string} loadItem The item to be loaded.
+ * @param {Boolean} [preferXHR] Determines if the LoadItem should try and load using XHR, or take a
+ * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
+ * other, so this is a suggested directive.
+ * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
+ * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
+ * @extends EventDispatcher
+ */
+function AbstractLoader(loadItem, preferXHR, type) {
+ this.EventDispatcher_constructor();
+
+ // public properties
+ /**
+ * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
+ * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
+ * @property loaded
+ * @type {Boolean}
+ * @default false
+ */
+ this.loaded = false;
+
+ /**
+ * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
+ * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
+ * instead.
+ * @property canceled
+ * @type {Boolean}
+ * @default false
+ * @readonly
+ */
+ this.canceled = false;
+
+ /**
+ * The current load progress (percentage) for this item. This will be a number between 0 and 1.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.loadFile("largeImage.png");
+ * queue.on("progress", function() {
+ * console.log("Progress:", queue.progress, event.progress);
+ * });
+ *
+ * @property progress
+ * @type {Number}
+ * @default 0
+ */
+ this.progress = 0;
+
+ /**
+ * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
+ * supported types.
+ * @property type
+ * @type {String}
+ */
+ this.type = type;
+
+ /**
+ * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
+ * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
+ * can be overridden to provide custom formatting.
+ *
+ * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
+ * asynchronous, such as creating a new image. The callback function is passed 2 parameters, which are callbacks
+ * to handle success and error conditions in the resultFormatter. Note that the resultFormatter method is
+ * called in the current scope, as well as the success and error callbacks.
+ *
+ * Example asynchronous resultFormatter
+ *
+ * function _formatResult(loader) {
+ * return function(success, error) {
+ * if (errorCondition) { error(errorDetailEvent); }
+ * success(result);
+ * }
+ * }
+ * @property resultFormatter
+ * @type {Function}
+ * @default null
+ */
+ this.resultFormatter = null;
+
+ // protected properties
+ /**
+ * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
+ * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
+ * @property _item
+ * @type {LoadItem|Object}
+ * @private
+ */
+ if (loadItem) {
+ this._item = LoadItem.create(loadItem);
+ } else {
+ this._item = null;
+ }
+
+ /**
+ * Whether the loader will try and load content using XHR (true) or HTML tags (false).
+ * @property _preferXHR
+ * @type {Boolean}
+ * @private
+ */
+ this._preferXHR = preferXHR;
+
+ /**
+ * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
+ * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
+ * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
+ * @property _result
+ * @type {Object|String}
+ * @private
+ */
+ this._result = null;
+
+ /**
+ * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
+ * method, and passing `true`.
+ * @property _rawResult
+ * @type {Object|String}
+ * @private
+ */
+ this._rawResult = null;
+
+ /**
+ * A list of items that loaders load behind the scenes. This does not include the main item the loader is
+ * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _loadItems
+ * @type {null}
+ * @protected
+ */
+ this._loadedItems = null;
+
+ /**
+ * The attribute the items loaded using tags use for the source.
+ * @type {string}
+ * @default null
+ * @private
+ */
+ this._tagSrcAttribute = null;
+
+ /**
+ * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
+ * @property _tag
+ * @type {Object}
+ * @private
+ */
+ this._tag = null;
+};
+
+var p = extend(AbstractLoader, EventDispatcher);
+var s = AbstractLoader;
+
+// TODO: deprecated
+// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
+
+
+/**
+ * Defines a POST request, use for a method value when loading data.
+ * @property POST
+ * @type {string}
+ * @default post
+ * @static
+ */
+s.POST = "POST";
+
+/**
+ * Defines a GET request, use for a method value when loading data.
+ * @property GET
+ * @type {string}
+ * @default get
+ * @static
+ */
+s.GET = "GET";
+
+/**
+ * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @since 0.6.0
+ */
+s.BINARY = "binary";
+
+/**
+ * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a
+ * <style> tag when loaded with tags.
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @since 0.6.0
+ */
+s.CSS = "css";
+
+/**
+ * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag.
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @since 0.6.0
+ */
+s.IMAGE = "image";
+
+/**
+ * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
+ * <script> tag.
+ *
+ * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
+ * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
+ * only tag-loaded scripts are injected.
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @since 0.6.0
+ */
+s.JAVASCRIPT = "javascript";
+
+/**
+ * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
+ * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
+ * must contain a matching wrapper function.
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @since 0.6.0
+ */
+s.JSON = "json";
+
+/**
+ * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
+ * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
+ * property is set to.
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @since 0.6.0
+ */
+s.JSONP = "jsonp";
+
+/**
+ * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
+ * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
+ * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
+ * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.6.0
+ */
+s.MANIFEST = "manifest";
+
+/**
+ * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
+ * <audio> tag.
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @since 0.6.0
+ */
+s.SOUND = "sound";
+
+/**
+ * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
+ * <video> tag.
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @since 0.6.0
+ */
+s.VIDEO = "video";
+
+/**
+ * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
+ * @property SPRITESHEET
+ * @type {String}
+ * @default spritesheet
+ * @static
+ * @since 0.6.0
+ */
+s.SPRITESHEET = "spritesheet";
+
+/**
+ * The preload type for SVG files.
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @since 0.6.0
+ */
+s.SVG = "svg";
+
+/**
+ * The preload type for text files, which is also the default file type if the type can not be determined. Text is
+ * loaded as raw text.
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @since 0.6.0
+ */
+s.TEXT = "text";
+
+/**
+ * The preload type for xml files. XML is loaded into an XML document.
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @since 0.6.0
+ */
+s.XML = "xml";
+
+// Events
+/**
+ * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
+ * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event progress
+ * @since 0.3.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
+ * @event loadstart
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.1
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
+ * @event complete
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.0
+ */
+
+/**
+ * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
+ * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
+ * just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event error
+ * @since 0.3.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
+ * This enables loaders to maintain internal queues, and surface file load errors.
+ * @event fileerror
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The even type ("fileerror")
+ * @param {LoadItem|object} The item that encountered the error
+ * @since 0.6.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
+ * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
+ * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
+ * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("fileload")
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.6.0
+ */
+
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
+ * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
+ * @event initialize
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("initialize")
+ * @param {AbstractLoader} loader The loader that has been initialized.
+ */
+
+
+/**
+ * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
+ * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
+ * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @method getItem
+ * @return {Object} The manifest item that this loader is responsible for loading.
+ * @since 0.6.0
+ */
+p.getItem = function () {
+ return this._item;
+};
+
+/**
+ * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
+ * event is dispatched.
+ * @method getResult
+ * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
+ * data (if it exists).
+ * @return {Object}
+ * @since 0.6.0
+ */
+p.getResult = function (raw) {
+ return raw ? this._rawResult : this._result;
+};
+
+/**
+ * Return the `tag` this object creates or uses for loading.
+ * @method getTag
+ * @return {Object} The tag instance
+ * @since 0.6.0
+ */
+p.getTag = function () {
+ return this._tag;
+};
+
+/**
+ * Set the `tag` this item uses for loading.
+ * @method setTag
+ * @param {Object} tag The tag instance
+ * @since 0.6.0
+ */
+p.setTag = function (tag) {
+ this._tag = tag;
+};
+
+/**
+ * Begin loading the item. This method is required when using a loader by itself.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.on("complete", handleComplete);
+ * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
+ * queue.load();
+ *
+ * @method load
+ */
+p.load = function () {
+ this._createRequest();
+
+ this._request.on("complete", this, this);
+ this._request.on("progress", this, this);
+ this._request.on("loadStart", this, this);
+ this._request.on("abort", this, this);
+ this._request.on("timeout", this, this);
+ this._request.on("error", this, this);
+
+ var evt = new Event("initialize");
+ evt.loader = this._request;
+ this.dispatchEvent(evt);
+
+ this._request.load();
+};
+
+/**
+ * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
+ * the background), but events will not longer be dispatched.
+ * @method cancel
+ */
+p.cancel = function () {
+ this.canceled = true;
+ this.destroy();
+};
+
+/**
+ * Clean up the loader.
+ * @method destroy
+ */
+p.destroy = function () {
+ if (this._request) {
+ this._request.removeAllEventListeners();
+ this._request.destroy();
+ }
+
+ this._request = null;
+
+ this._item = null;
+ this._rawResult = null;
+ this._result = null;
+
+ this._loadItems = null;
+
+ this.removeAllEventListeners();
+};
+
+/**
+ * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to expose items it loads internally.
+ * @method getLoadedItems
+ * @return {Array} A list of the items loaded by the loader.
+ * @since 0.6.0
+ */
+p.getLoadedItems = function () {
+ return this._loadedItems;
+};
+
+
+// Private methods
+/**
+ * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
+ * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
+ * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
+ * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
+ * @method _createRequest
+ * @protected
+ */
+p._createRequest = function () {
+ if (!this._preferXHR) {
+ this._request = new TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ } else {
+ this._request = new XHRRequest(this._item);
+ }
+};
+
+/**
+ * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
+ * by loaders that require tag loading.
+ * @method _createTag
+ * @param {String} src The tag source
+ * @return {HTMLElement} The tag that was created
+ * @protected
+ */
+p._createTag = function (src) {
+ return null;
+};
+
+/**
+ * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendLoadStart
+ * @protected
+ */
+p._sendLoadStart = function () {
+ if (this._isCanceled()) {
+ return;
+ }
+ this.dispatchEvent("loadstart");
+};
+
+/**
+ * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
+ * @method _sendProgress
+ * @param {Number | Object} value The progress of the loaded item, or an object containing loaded
+ * and total
properties.
+ * @protected
+ */
+p._sendProgress = function (value) {
+ if (this._isCanceled()) {
+ return;
+ }
+ var event = null;
+ if (typeof(value) == "number") {
+ this.progress = value;
+ event = new ProgressEvent(this.progress);
+ } else {
+ event = value;
+ this.progress = value.loaded / value.total;
+ event.progress = this.progress;
+ if (isNaN(this.progress) || this.progress == Infinity) {
+ this.progress = 0;
+ }
+ }
+ this.hasEventListener("progress") && this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
+ * @method _sendComplete
+ * @protected
+ */
+p._sendComplete = function () {
+ if (this._isCanceled()) {
+ return;
+ }
+
+ this.loaded = true;
+
+ var event = new Event("complete");
+ event.rawResult = this._rawResult;
+
+ if (this._result != null) {
+ event.result = this._result;
+ }
+
+ this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendError
+ * @param {ErrorEvent} event The event object containing specific error properties.
+ * @protected
+ */
+p._sendError = function (event) {
+ if (this._isCanceled() || !this.hasEventListener("error")) {
+ return;
+ }
+ if (event == null) {
+ event = new ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
+ }
+ this.dispatchEvent(event);
+};
+
+/**
+ * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
+ * do not cause issues after the queue has been cleaned up.
+ * @method _isCanceled
+ * @return {Boolean} If the loader has been canceled.
+ * @protected
+ */
+p._isCanceled = function () {
+ if (window.createjs == null || this.canceled) {
+ return true;
+ }
+ return false;
+};
+
+/**
+ * A custom result formatter function, which is called just before a request dispatches its complete event. Most
+ * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
+ * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
+ * @property resultFormatter
+ * @type Function
+ * @return {Object} The formatted result
+ * @since 0.6.0
+ */
+p.resultFormatter = null;
+
+/**
+ * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
+ * this method can be overridden for custom behaviours.
+ * @method handleEvent
+ * @param {Event} event The event that the internal request dispatches.
+ * @protected
+ * @since 0.6.0
+ */
+p.handleEvent = function (event) {
+ switch (event.type) {
+ case "complete":
+ this._rawResult = event.target._response;
+ var result = this.resultFormatter && this.resultFormatter(this);
+ if (result instanceof Function) {
+ result.call(this,
+ proxy(this._resultFormatSuccess, this),
+ proxy(this._resultFormatFailed, this)
+ );
+ } else {
+ this._result = result || this._rawResult;
+ this._sendComplete();
+ }
+ break;
+ case "progress":
+ this._sendProgress(event);
+ break;
+ case "error":
+ this._sendError(event);
+ break;
+ case "loadstart":
+ this._sendLoadStart();
+ break;
+ case "abort":
+ case "timeout":
+ if (!this._isCanceled()) {
+ this.dispatchEvent(new ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR"));
+ }
+ break;
+ }
+};
+
+/**
+ * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} result The formatted result
+ * @private
+ */
+p._resultFormatSuccess = function (result) {
+ this._result = result;
+ this._sendComplete();
+};
+
+/**
+ * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} error The error event
+ * @private
+ */
+p._resultFormatFailed = function (event) {
+ this._sendError(event);
+};
+
+/**
+ * @method buildPath
+ * @protected
+ * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
+ * instead.
+ */
+p.buildPath = function (src, data) {
+ return RequestUtils.buildPath(src, data);
+};
+
+/**
+ * @method toString
+ * @return {String} a string representation of the instance.
+ */
+p.toString = function () {
+ return "[PreloadJS AbstractLoader]";
+};
+
+module.exports = AbstractLoader = promote(AbstractLoader, "EventDispatcher");
+
+},{"../../createjs/events/ErrorEvent":1,"../../createjs/events/Event":2,"../../createjs/events/EventDispatcher":3,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"../data/LoadItem":8,"../events/ProgressEvent":9,"../net/TagRequest":13,"../net/XHRRequest":14,"../utils/RequestUtils":15}],11:[function(_dereq_,module,exports){
+/*
+ * ImageLoader
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+// constructor
+/**
+ * A loader for image files.
+ * @class ImageLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractLoader
+ * @constructor
+ */
+
+var AbstractLoader = _dereq_('./AbstractLoader');
+var RequestUtils = _dereq_('../utils/RequestUtils');
+var extend = _dereq_('../../createjs/utils/extend');
+var promote = _dereq_('../../createjs/utils/promote');
+var proxy = _dereq_('../../createjs/utils/proxy');
+
+function ImageLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, AbstractLoader.IMAGE);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "src";
+
+ // Check if the preload item is already a tag.
+ if (RequestUtils.isImageTag(loadItem)) {
+ this._tag = loadItem;
+ } else if (RequestUtils.isImageTag(loadItem.src)) {
+ this._tag = loadItem.src;
+ } else if (RequestUtils.isImageTag(loadItem.tag)) {
+ this._tag = loadItem.tag;
+ }
+
+ if (this._tag != null) {
+ this._preferXHR = false;
+ } else {
+ this._tag = document.createElement("img");
+ }
+
+ this.on("initialize", this._updateXHR, this);
+};
+
+var p = extend(ImageLoader, AbstractLoader);
+var s = ImageLoader;
+
+// static methods
+/**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+s.canLoadItem = function (item) {
+ return item.type == AbstractLoader.IMAGE;
+};
+
+// public methods
+p.load = function () {
+ if (this._tag.src != "" && this._tag.complete) {
+ this._sendComplete();
+ return;
+ }
+
+ var crossOrigin = this._item.crossOrigin;
+ if (crossOrigin == true) {
+ crossOrigin = "Anonymous";
+ }
+ if (crossOrigin != null && !RequestUtils.isLocal(this._item.src)) {
+ this._tag.crossOrigin = crossOrigin;
+ }
+
+ this.AbstractLoader_load();
+};
+
+// protected methods
+/**
+ * Before the item loads, set its mimeType and responseType.
+ * @property _updateXHR
+ * @param {Event} event
+ * @private
+ */
+p._updateXHR = function (event) {
+ event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';
+
+ // Only exists for XHR
+ if (event.loader.setResponseType) {
+ event.loader.setResponseType("blob");
+ }
+};
+
+/**
+ * The result formatter for Image files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLImageElement}
+ * @private
+ */
+p._formatResult = function (loader) {
+ return this._formatImage;
+};
+
+/**
+ * The asynchronous image formatter function. This is required because images have
+ * a short delay before they are ready.
+ * @method _formatImage
+ * @param {Function} successCallback The method to call when the result has finished formatting
+ * @param {Function} errorCallback The method to call if an error occurs during formatting
+ * @private
+ */
+p._formatImage = function (successCallback, errorCallback) {
+ var tag = this._tag;
+ var URL = window.URL || window.webkitURL;
+
+ if (!this._preferXHR) {
+ //document.body.removeChild(tag);
+ } else if (URL) {
+ var objURL = URL.createObjectURL(this.getResult(true));
+ tag.src = objURL;
+
+ tag.addEventListener("load", this._cleanUpURL, false);
+ tag.addEventListener("error", this._cleanUpURL, false);
+ } else {
+ tag.src = this._item.src;
+ }
+
+ if (tag.complete) {
+ successCallback(tag);
+ } else {
+ tag.onload = proxy(function () {
+ successCallback(this._tag);
+ }, this);
+
+ tag.onerror = proxy(function () {
+ errorCallback(_this._tag);
+ }, this);
+ }
+};
+
+/**
+ * Clean up the ObjectURL, the tag is done with it. Note that this function is run
+ * as an event listener without a proxy/closure, as it doesn't require it - so do not
+ * include any functionality that requires scope without changing it.
+ * @method _cleanUpURL
+ * @param event
+ * @private
+ */
+p._cleanUpURL = function (event) {
+ var URL = window.URL || window.webkitURL;
+ URL.revokeObjectURL(event.target.src);
+};
+
+var ImageLoader = promote(ImageLoader, "AbstractLoader");
+module.exports = ImageLoader;
+
+},{"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"../utils/RequestUtils":15,"./AbstractLoader":10}],12:[function(_dereq_,module,exports){
+/*
+ * AbstractRequest
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var promote = _dereq_('../../createjs/utils/promote');
+var extend = _dereq_('../../createjs/utils/extend');
+var EventDispatcher = _dereq_('../../createjs/events/EventDispatcher');
+
+/**
+ * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
+ * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
+ * hood to get data.
+ * @class AbstractRequest
+ * @param {LoadItem} item
+ * @constructor
+ */
+var AbstractRequest = function (item) {
+ this._item = item;
+};
+
+var p = extend(AbstractRequest, EventDispatcher);
+
+// public methods
+/**
+ * Begin a load.
+ * @method load
+ */
+p.load = function () {
+};
+
+/**
+ * Clean up a request.
+ * @method destroy
+ */
+p.destroy = function () {
+};
+
+/**
+ * Cancel an in-progress request.
+ * @method cancel
+ */
+p.cancel = function () {
+};
+
+module.exports = AbstractRequest = promote(AbstractRequest, "EventDispatcher");
+
+},{"../../createjs/events/EventDispatcher":3,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5}],13:[function(_dereq_,module,exports){
+/*
+ * TagRequest
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var proxy = _dereq_('../../createjs/utils/proxy');
+var extend = _dereq_('../../createjs/utils/extend');
+var AbstractRequest = _dereq_('./AbstractRequest');
+var Event = _dereq_('../../createjs/events/Event');
+var promote = _dereq_('../../createjs/utils/promote');
+
+// constructor
+/**
+ * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
+ * @class TagRequest
+ * @param {LoadItem} loadItem
+ * @param {HTMLElement} tag
+ * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
+ */
+function TagRequest(loadItem, tag, srcAttribute) {
+ this.AbstractRequest_constructor(loadItem);
+
+ // protected properties
+ /**
+ * The HTML tag instance that is used to load.
+ * @property _tag
+ * @type {HTMLElement}
+ * @protected
+ */
+ this._tag = tag;
+
+ /**
+ * The tag attribute that specifies the source, such as "src", "href", etc.
+ * @property _tagSrcAttribute
+ * @type {String}
+ * @protected
+ */
+ this._tagSrcAttribute = srcAttribute;
+
+ /**
+ * A method closure used for handling the tag load event.
+ * @property _loadedHandler
+ * @type {Function}
+ * @private
+ */
+ this._loadedHandler = proxy(this._handleTagComplete, this);
+
+ /**
+ * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
+ * @property _addedToDOM
+ * @type {Boolean}
+ * @private
+ */
+ this._addedToDOM = false;
+
+ /**
+ * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
+ *
+ * @type {null}
+ * @private
+ */
+ this._startTagVisibility = null;
+};
+
+var p = extend(TagRequest, AbstractRequest);
+
+// public methods
+p.load = function () {
+ this._tag.onload = proxy(this._handleTagComplete, this);
+ this._tag.onreadystatechange = proxy(this._handleReadyStateChange, this);
+ this._tag.onerror = proxy(this._handleError, this);
+
+ var evt = new Event("initialize");
+ evt.loader = this._tag;
+
+ this.dispatchEvent(evt);
+
+ this._hideTag();
+
+ this._loadTimeout = setTimeout(proxy(this._handleTimeout, this), this._item.loadTimeout);
+
+ this._tag[this._tagSrcAttribute] = this._item.src;
+
+ // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
+ if (this._tag.parentNode == null) {
+ window.document.body.appendChild(this._tag);
+ this._addedToDOM = true;
+ }
+};
+
+p.destroy = function () {
+ this._clean();
+ this._tag = null;
+
+ this.AbstractRequest_destroy();
+};
+
+// private methods
+/**
+ * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
+ * and LINK tags), but other cases may exist.
+ * @method _handleReadyStateChange
+ * @private
+ */
+p._handleReadyStateChange = function () {
+ clearTimeout(this._loadTimeout);
+ // This is strictly for tags in browsers that do not support onload.
+ var tag = this._tag;
+
+ // Complete is for old IE support.
+ if (tag.readyState == "loaded" || tag.readyState == "complete") {
+ this._handleTagComplete();
+ }
+};
+
+/**
+ * Handle any error events from the tag.
+ * @method _handleError
+ * @protected
+ */
+p._handleError = function () {
+ this._clean();
+ this.dispatchEvent("error");
+};
+
+/**
+ * Handle the tag's onload callback.
+ * @method _handleTagComplete
+ * @private
+ */
+p._handleTagComplete = function () {
+ this._rawResult = this._tag;
+ this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;
+
+ this._clean();
+ this._showTag();
+
+ this.dispatchEvent("complete");
+};
+
+/**
+ * The tag request has not loaded within the time specified in loadTimeout.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+p._handleTimeout = function () {
+ this._clean();
+ this.dispatchEvent(new Event("timeout"));
+};
+
+/**
+ * Remove event listeners, but don't destroy the request object
+ * @method _clean
+ * @private
+ */
+p._clean = function () {
+ this._tag.onload = null;
+ this._tag.onreadystatechange = null;
+ this._tag.onerror = null;
+ if (this._addedToDOM && this._tag.parentNode != null) {
+ this._tag.parentNode.removeChild(this._tag);
+ }
+ clearTimeout(this._loadTimeout);
+};
+
+p._hideTag = function () {
+ this._startTagVisibility = this._tag.style.visibility;
+ this._tag.style.visibility = "hidden";
+};
+
+p._showTag = function () {
+ this._tag.style.visibility = this._startTagVisibility;
+};
+
+/**
+ * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
+ * that is already in a load, but not complete.
+ * @method _handleStalled
+ * @private
+ */
+p._handleStalled = function () {
+ //Ignore, let the timeout take care of it. Sometimes its not really stopped.
+};
+
+module.exports = promote(TagRequest, "AbstractRequest");
+},{"../../createjs/events/Event":2,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"./AbstractRequest":12}],14:[function(_dereq_,module,exports){
+/*
+ * XHRRequest
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+var proxy = _dereq_('../../createjs/utils/proxy');
+var extend = _dereq_('../../createjs/utils/extend');
+var promote = _dereq_('../../createjs/utils/promote');
+var AbstractRequest = _dereq_('./AbstractRequest');
+var AbstractLoader = _dereq_('../loaders/AbstractLoader');
+var RequestUtils = _dereq_('../utils/RequestUtils');
+var ErrorEvent = _dereq_('../../createjs/events/ErrorEvent');
+var ProgressEvent = _dereq_('../events/ProgressEvent');
+
+/**
+ * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
+ * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
+ * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
+ * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
+ * cross-domain loading.
+ * @class XHRRequest
+ * @constructor
+ * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * for an overview of supported file properties.
+ * @extends AbstractLoader
+ */
+function XHRRequest(item) {
+ this.AbstractRequest_constructor(item);
+
+ // protected properties
+ /**
+ * A reference to the XHR request used to load the content.
+ * @property _request
+ * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
+ * @private
+ */
+ this._request = null;
+
+ /**
+ * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
+ * typically IE9).
+ * @property _loadTimeout
+ * @type {Number}
+ * @private
+ */
+ this._loadTimeout = null;
+
+ /**
+ * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
+ * the version, so we use capabilities to make a best guess.
+ * @property _xhrLevel
+ * @type {Number}
+ * @default 1
+ * @private
+ */
+ this._xhrLevel = 1;
+
+ /**
+ * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
+ * null until the file is loaded.
+ * @property _response
+ * @type {mixed}
+ * @private
+ */
+ this._response = null;
+
+ /**
+ * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
+ * an HTML tag or a formatted object which is set to the result
property, but the developer may still
+ * want to access the raw content as it was loaded.
+ * @property _rawResponse
+ * @type {String|Object}
+ * @private
+ */
+ this._rawResponse = null;
+
+ this._canceled = false;
+
+ // Setup our event handlers now.
+ this._handleLoadStartProxy = proxy(this._handleLoadStart, this);
+ this._handleProgressProxy = proxy(this._handleProgress, this);
+ this._handleAbortProxy = proxy(this._handleAbort, this);
+ this._handleErrorProxy = proxy(this._handleError, this);
+ this._handleTimeoutProxy = proxy(this._handleTimeout, this);
+ this._handleLoadProxy = proxy(this._handleLoad, this);
+ this._handleReadyStateChangeProxy = proxy(this._handleReadyStateChange, this);
+
+ if (!this._createXHR(item)) {
+ //TODO: Throw error?
+ }
+};
+
+var p = extend(XHRRequest, AbstractRequest);
+
+// static properties
+/**
+ * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
+ * @property ACTIVEX_VERSIONS
+ * @type {Array}
+ * @since 0.4.2
+ * @private
+ */
+XHRRequest.ACTIVEX_VERSIONS = [
+ "Msxml2.XMLHTTP.6.0",
+ "Msxml2.XMLHTTP.5.0",
+ "Msxml2.XMLHTTP.4.0",
+ "MSXML2.XMLHTTP.3.0",
+ "MSXML2.XMLHTTP",
+ "Microsoft.XMLHTTP"
+];
+
+// Public methods
+/**
+ * Look up the loaded result.
+ * @method getResult
+ * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the
+ * HTML head.
+ * - A style tag for CSS (<style />)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - An binary arraybuffer loaded by XHR
+ *
+ * Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+p.getResult = function (raw) {
+ if (raw && this._rawResponse) {
+ return this._rawResponse;
+ }
+ return this._response;
+};
+
+// Overrides abstract method in AbstractRequest
+p.cancel = function () {
+ this.canceled = true;
+ this._clean();
+ this._request.abort();
+};
+
+// Overrides abstract method in AbstractLoader
+p.load = function () {
+ if (this._request == null) {
+ this._handleError();
+ return;
+ }
+
+ //Events
+ if (this._request.addEventListener != null) {
+ this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
+ this._request.addEventListener("progress", this._handleProgressProxy, false);
+ this._request.addEventListener("abort", this._handleAbortProxy, false);
+ this._request.addEventListener("error", this._handleErrorProxy, false);
+ this._request.addEventListener("timeout", this._handleTimeoutProxy, false);
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.addEventListener("load", this._handleLoadProxy, false);
+ this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
+ } else {
+ // IE9 support
+ this._request.onloadstart = this._handleLoadStartProxy;
+ this._request.onprogress = this._handleProgressProxy;
+ this._request.onabort = this._handleAbortProxy;
+ this._request.onerror = this._handleErrorProxy;
+ this._request.ontimeout = this._handleTimeoutProxy;
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.onload = this._handleLoadProxy;
+ this._request.onreadystatechange = this._handleReadyStateChangeProxy;
+ }
+
+ // Set up a timeout if we don't have XHR2
+ if (this._xhrLevel == 1) {
+ this._loadTimeout = setTimeout(proxy(this._handleTimeout, this), this._item.loadTimeout);
+ }
+
+ // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome
+ try {
+ if (!this._item.values || this._item.method == AbstractLoader.GET) {
+ this._request.send();
+ } else if (this._item.method == AbstractLoader.POST) {
+ this._request.send(RequestUtils.formatQueryString(this._item.values));
+ }
+ } catch (error) {
+ this.dispatchEvent(new ErrorEvent("XHR_SEND", null, error));
+ }
+};
+
+p.setResponseType = function (type) {
+ // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
+ if (type === 'blob') {
+ type = window.URL ? 'blob' : 'arraybuffer';
+ this._responseType = type;
+ }
+ this._request.responseType = type;
+};
+
+/**
+ * Get all the response headers from the XmlHttpRequest.
+ *
+ * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match
+ * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
+ * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
+ * pair.
+ * @method getAllResponseHeaders
+ * @return {String}
+ * @since 0.4.1
+ */
+p.getAllResponseHeaders = function () {
+ if (this._request.getAllResponseHeaders instanceof Function) {
+ return this._request.getAllResponseHeaders();
+ } else {
+ return null;
+ }
+};
+
+/**
+ * Get a specific response header from the XmlHttpRequest.
+ *
+ * From the docs: Returns the header field value from the response of which the field name matches
+ * header, unless the field name is Set-Cookie or Set-Cookie2.
+ * @method getResponseHeader
+ * @param {String} header The header name to retrieve.
+ * @return {String}
+ * @since 0.4.1
+ */
+p.getResponseHeader = function (header) {
+ if (this._request.getResponseHeader instanceof Function) {
+ return this._request.getResponseHeader(header);
+ } else {
+ return null;
+ }
+};
+
+// protected methods
+/**
+ * The XHR request has reported progress.
+ * @method _handleProgress
+ * @param {Object} event The XHR progress event.
+ * @private
+ */
+p._handleProgress = function (event) {
+ if (!event || event.loaded > 0 && event.total == 0) {
+ return; // Sometimes we get no "total", so just ignore the progress event.
+ }
+
+ var newEvent = new ProgressEvent(event.loaded, event.total);
+ this.dispatchEvent(newEvent);
+};
+
+/**
+ * The XHR request has reported a load start.
+ * @method _handleLoadStart
+ * @param {Object} event The XHR loadStart event.
+ * @private
+ */
+p._handleLoadStart = function (event) {
+ clearTimeout(this._loadTimeout);
+ this.dispatchEvent("loadstart");
+};
+
+/**
+ * The XHR request has reported an abort event.
+ * @method handleAbort
+ * @param {Object} event The XHR abort event.
+ * @private
+ */
+p._handleAbort = function (event) {
+ this._clean();
+ this.dispatchEvent(new ErrorEvent("XHR_ABORTED", null, event));
+};
+
+/**
+ * The XHR request has reported an error event.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+p._handleError = function (event) {
+ this._clean();
+ this.dispatchEvent(new ErrorEvent(event.message));
+};
+
+/**
+ * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
+ * event, so we must monitor the readyStateChange to determine if the file is loaded.
+ * @method _handleReadyStateChange
+ * @param {Object} event The XHR readyStateChange event.
+ * @private
+ */
+p._handleReadyStateChange = function (event) {
+ if (this._request.readyState == 4) {
+ this._handleLoad();
+ }
+};
+
+/**
+ * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
+ * request.readyState == 4
. Only the first call to this method will be processed.
+ * @method _handleLoad
+ * @param {Object} event The XHR load event.
+ * @private
+ */
+p._handleLoad = function (event) {
+ if (this.loaded) {
+ return;
+ }
+ this.loaded = true;
+
+ var error = this._checkError();
+ if (error) {
+ this._handleError(error);
+ return;
+ }
+
+ this._response = this._getResponse();
+ // Convert arraybuffer back to blob
+ if (this._responseType === 'arraybuffer') {
+ try {
+ this._response = new Blob([this._response]);
+ } catch (e) {
+ // Fallback to use BlobBuilder if Blob constructor is not supported
+ // Tested on Android 2.3 ~ 4.2 and iOS5 safari
+ window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ if (e.name === 'TypeError' && window.BlobBuilder) {
+ var builder = new BlobBuilder();
+ builder.append(this._response);
+ this._response = builder.getBlob();
+ }
+ }
+ }
+ this._clean();
+
+ this.dispatchEvent(new Event("complete"));
+};
+
+/**
+ * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout
+ * callback.
+ * @method _handleTimeout
+ * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
+ * @private
+ */
+p._handleTimeout = function (event) {
+ this._clean();
+
+ this.dispatchEvent(new ErrorEvent("PRELOAD_TIMEOUT", null, event));
+};
+
+// Protected
+/**
+ * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
+ * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
+ * @method _checkError
+ * @return {int} If the request status returns an error code.
+ * @private
+ */
+p._checkError = function () {
+ //LM: Probably need additional handlers here, maybe 501
+ var status = parseInt(this._request.status);
+
+ switch (status) {
+ case 404: // Not Found
+ case 0: // Not Loaded
+ return new Error(status);
+ }
+ return null;
+};
+
+/**
+ * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
+ * in other browsers. If there is no response, the _response
property will remain null.
+ * @method _getResponse
+ * @private
+ */
+p._getResponse = function () {
+ if (this._response != null) {
+ return this._response;
+ }
+
+ if (this._request.response != null) {
+ return this._request.response;
+ }
+
+ // Android 2.2 uses .responseText
+ try {
+ if (this._request.responseText != null) {
+ return this._request.responseText;
+ }
+ } catch (e) {
+ }
+
+ // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
+ try {
+ if (this._request.responseXML != null) {
+ return this._request.responseXML;
+ }
+ } catch (e) {
+ }
+
+ return null;
+};
+
+/**
+ * Create an XHR request. Depending on a number of factors, we get totally different results.
+ * - Some browsers get an
XDomainRequest
when loading cross-domain.
+ * - XMLHttpRequest are created when available.
+ * - ActiveX.XMLHTTP objects are used in older IE browsers.
+ * - Text requests override the mime type if possible
+ * - Origin headers are sent for crossdomain requests in some browsers.
+ * - Binary loads set the response type to "arraybuffer"
+ * @method _createXHR
+ * @param {Object} item The requested item that is being loaded.
+ * @return {Boolean} If an XHR request or equivalent was successfully created.
+ * @private
+ */
+p._createXHR = function (item) {
+ // Check for cross-domain loads. We can't fully support them, but we can try.
+ var crossdomain = RequestUtils.isCrossDomain(item);
+ var headers = {};
+
+ // Create the request. Fallback to whatever support we have.
+ var req = null;
+ if (window.XMLHttpRequest) {
+ req = new XMLHttpRequest();
+ // This is 8 or 9, so use XDomainRequest instead.
+ if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
+ req = new XDomainRequest();
+ }
+ } else { // Old IE versions use a different approach
+ for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
+ var axVersion = s.ACTIVEX_VERSIONS[i];
+ try {
+ req = new ActiveXObject(axVersion);
+ break;
+ } catch (e) {
+ }
+ }
+ if (req == null) {
+ return false;
+ }
+ }
+
+ // Default to utf-8 for Text requests.
+ if (item.mimeType == null && RequestUtils.isText(item.type)) {
+ item.mimeType = "text/plain; charset=utf-8";
+ }
+
+ // IE9 doesn't support overrideMimeType(), so we need to check for it.
+ if (item.mimeType && req.overrideMimeType) {
+ req.overrideMimeType(item.mimeType);
+ }
+
+ // Determine the XHR level
+ this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;
+
+ var src = null;
+ if (item.method == AbstractLoader.GET) {
+ src = RequestUtils.buildPath(item.src, item.values);
+ } else {
+ src = item.src;
+ }
+
+ // Open the request. Set cross-domain flags if it is supported (XHR level 1 only)
+ req.open(item.method || AbstractLoader.GET, src, true);
+
+ if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
+ headers["Origin"] = location.origin;
+ }
+
+ // To send data we need to set the Content-type header)
+ if (item.values && item.method == AbstractLoader.POST) {
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+
+ if (!crossdomain && !headers["X-Requested-With"]) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ if (item.headers) {
+ for (var n in item.headers) {
+ headers[n] = item.headers[n];
+ }
+ }
+
+ for (n in headers) {
+ req.setRequestHeader(n, headers[n])
+ }
+
+ if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
+ req.withCredentials = item.withCredentials;
+ }
+
+ this._request = req;
+
+ return true;
+};
+
+/**
+ * A request has completed (or failed or canceled), and needs to be disposed.
+ * @method _clean
+ * @private
+ */
+p._clean = function () {
+ clearTimeout(this._loadTimeout);
+
+ if (this._request.removeEventListener != null) {
+ this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
+ this._request.removeEventListener("progress", this._handleProgressProxy);
+ this._request.removeEventListener("abort", this._handleAbortProxy);
+ this._request.removeEventListener("error", this._handleErrorProxy);
+ this._request.removeEventListener("timeout", this._handleTimeoutProxy);
+ this._request.removeEventListener("load", this._handleLoadProxy);
+ this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
+ } else {
+ this._request.onloadstart = null;
+ this._request.onprogress = null;
+ this._request.onabort = null;
+ this._request.onerror = null;
+ this._request.ontimeout = null;
+ this._request.onload = null;
+ this._request.onreadystatechange = null;
+ }
+};
+
+p.toString = function () {
+ return "[PreloadJS XHRRequest]";
+};
+
+module.exports = XHRRequest = promote(XHRRequest, "AbstractRequest");
+
+},{"../../createjs/events/ErrorEvent":1,"../../createjs/utils/extend":4,"../../createjs/utils/promote":5,"../../createjs/utils/proxy":6,"../events/ProgressEvent":9,"../loaders/AbstractLoader":10,"../utils/RequestUtils":15,"./AbstractRequest":12}],15:[function(_dereq_,module,exports){
+/*
+ * RequestUtils
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ *
+ * Copyright (c) 2012 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @module PreloadJS
+ */
+
+
+var AbstractLoader = _dereq_('../loaders/AbstractLoader');
+
+/**
+ * Utilities that assist with parsing load items, and determining file types, etc.
+ * @class RequestUtils
+ */
+var s = {};
+
+/**
+ * The Regular Expression used to test file URLS for an absolute path.
+ * @property ABSOLUTE_PATH
+ * @type {RegExp}
+ * @static
+ */
+s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
+
+/**
+ * The Regular Expression used to test file URLS for a relative path.
+ * @property RELATIVE_PATH
+ * @type {RegExp}
+ * @static
+ */
+s.RELATIVE_PATT = (/^[./]*?\//i);
+
+/**
+ * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
+ * removed.
+ * @property EXTENSION_PATT
+ * @type {RegExp}
+ * @static
+ */
+s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
+
+/**
+ * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
+ *
+ * - If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
+ * `//networkPath`)
+ * - If the path is relative. Relative paths start with `../` or `/path` (or similar)
+ * - The file extension. This is determined by the filename with an extension. Query strings are dropped, and
+ * the file path is expected to follow the format `name.ext`.
+ *
+ * @method parseURI
+ * @param {String} path
+ * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
+ * property, which is the lowercase extension.
+ * @static
+ */
+s.parseURI = function (path) {
+ var info = {absolute: false, relative: false};
+ if (path == null) {
+ return info;
+ }
+
+ // Drop the query string
+ var queryIndex = path.indexOf("?");
+ if (queryIndex > -1) {
+ path = path.substr(0, queryIndex);
+ }
+
+ // Absolute
+ var match;
+ if (s.ABSOLUTE_PATT.test(path)) {
+ info.absolute = true;
+
+ // Relative
+ } else if (s.RELATIVE_PATT.test(path)) {
+ info.relative = true;
+ }
+
+ // Extension
+ if (match = path.match(s.EXTENSION_PATT)) {
+ info.extension = match[1].toLowerCase();
+ }
+ return info;
+};
+
+/**
+ * Formats an object into a query string for either a POST or GET request.
+ * @method formatQueryString
+ * @param {Object} data The data to convert to a query string.
+ * @param {Array} [query] Existing name/value pairs to append on to this query.
+ * @static
+ */
+s.formatQueryString = function (data, query) {
+ if (data == null) {
+ throw new Error('You must specify data.');
+ }
+ var params = [];
+ for (var n in data) {
+ params.push(n + '=' + escape(data[n]));
+ }
+ if (query) {
+ params = params.concat(query);
+ }
+ return params.join('&');
+};
+
+/**
+ * A utility method that builds a file path using a source and a data object, and formats it into a new path.
+ * @method buildPath
+ * @param {String} src The source path to add values to.
+ * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
+ * path will be preserved.
+ * @returns {string} A formatted string that contains the path and the supplied parameters.
+ * @static
+ */
+s.buildPath = function (src, data) {
+ if (data == null) {
+ return src;
+ }
+
+ var query = [];
+ var idx = src.indexOf('?');
+
+ if (idx != -1) {
+ var q = src.slice(idx + 1);
+ query = query.concat(q.split('&'));
+ }
+
+ if (idx != -1) {
+ return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
+ } else {
+ return src + '?' + this._formatQueryString(data, query);
+ }
+};
+
+/**
+ * @method isCrossDomain
+ * @param {LoadItem|Object} item A load item with a `src` property.
+ * @return {Boolean} If the load item is loading from a different domain than the current location.
+ * @static
+ */
+s.isCrossDomain = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+
+ var host = document.createElement("a");
+ host.href = location.href;
+
+ var crossdomain = (target.hostname != "") &&
+ (target.port != host.port ||
+ target.protocol != host.protocol ||
+ target.hostname != host.hostname);
+ return crossdomain;
+};
+
+/**
+ * @method isLocal
+ * @param {LoadItem|Object} item A load item with a `src` property
+ * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
+ * well.
+ * @static
+ */
+s.isLocal = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+ return target.hostname == "" && target.protocol == "file:";
+};
+
+/**
+ * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
+ * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play
+ * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
+ * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
+ * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @method isBinary
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is binary.
+ * @static
+ */
+s.isBinary = function (type) {
+ switch (type) {
+ case AbstractLoader.IMAGE:
+ case AbstractLoader.BINARY:
+ return true;
+ default:
+ return false;
+ }
+};
+
+/**
+ * Check if item is a valid HTMLImageElement
+ * @method isImageTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isImageTag = function (item) {
+ return item instanceof HTMLImageElement;
+};
+
+/**
+ * Check if item is a valid HTMLAudioElement
+ * @method isAudioTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isAudioTag = function (item) {
+ if (window.HTMLAudioElement) {
+ return item instanceof HTMLAudioElement;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Check if item is a valid HTMLVideoElement
+ * @method isVideoTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isVideoTag = function (item) {
+ if (window.HTMLVideoElement) {
+ return item instanceof HTMLVideoElement;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
+ * @method isText
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is text.
+ * @static
+ */
+s.isText = function (type) {
+ switch (type) {
+ case AbstractLoader.TEXT:
+ case AbstractLoader.JSON:
+ case AbstractLoader.MANIFEST:
+ case AbstractLoader.XML:
+ case AbstractLoader.CSS:
+ case AbstractLoader.SVG:
+ case AbstractLoader.JAVASCRIPT:
+ case AbstractLoader.SPRITESHEET:
+ return true;
+ default:
+ return false;
+ }
+};
+
+/**
+ * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
+ * if it is an unusual extension.
+ * @method getTypeByExtension
+ * @param {String} extension The file extension to use to determine the load type.
+ * @return {String} The determined load type (for example, AbstractLoader.IMAGE
). Will return `null` if
+ * the type can not be determined by the extension.
+ * @static
+ */
+s.getTypeByExtension = function (extension) {
+ if (extension == null) {
+ return AbstractLoader.TEXT;
+ }
+
+ switch (extension.toLowerCase()) {
+ case "jpeg":
+ case "jpg":
+ case "gif":
+ case "png":
+ case "webp":
+ case "bmp":
+ return AbstractLoader.IMAGE;
+ case "ogg":
+ case "mp3":
+ case "webm":
+ return AbstractLoader.SOUND;
+ case "mp4":
+ case "webm":
+ case "ts":
+ return AbstractLoader.VIDEO;
+ case "json":
+ return AbstractLoader.JSON;
+ case "xml":
+ return AbstractLoader.XML;
+ case "css":
+ return AbstractLoader.CSS;
+ case "js":
+ return AbstractLoader.JAVASCRIPT;
+ case 'svg':
+ return AbstractLoader.SVG;
+ default:
+ return AbstractLoader.TEXT;
+ }
+};
+
+var RequestUtils = s;
+module.exports = RequestUtils;
+
+},{"../loaders/AbstractLoader":10}],16:[function(_dereq_,module,exports){
+// File for legacy window.createjs support. Also used for the the build process.
+(function (name, definition) {
+ if (typeof module != 'undefined') module.exports = definition();
+ else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
+ else this[name] = definition(); console.log(this, name);
+}('createjs', function () {
+ return {
+ LoadQueue: _dereq_("./LoadQueue"),
+ promote: _dereq_('../createjs/utils/promote'),
+ extend: _dereq_('../createjs/utils/extend'),
+ Event: _dereq_('../createjs/events/Event'),
+ ErrorEvent: _dereq_('../createjs/events/ErrorEvent'),
+ ProgressEvent: _dereq_('./events/ProgressEvent')
+ };
+}));
+
+},{"../createjs/events/ErrorEvent":1,"../createjs/events/Event":2,"../createjs/utils/extend":4,"../createjs/utils/promote":5,"./LoadQueue":7,"./events/ProgressEvent":9}]},{},[16]);
diff --git a/examples/moduleLoaders/window/index.html b/examples/moduleLoaders/window/index.html
new file mode 100644
index 0000000..1acc618
--- /dev/null
+++ b/examples/moduleLoaders/window/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+ Codestin Search App
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/preloadjs-NEXT.combined.js b/lib/preloadjs-NEXT.combined.js
index 420d408..c60b6ec 100644
--- a/lib/preloadjs-NEXT.combined.js
+++ b/lib/preloadjs-NEXT.combined.js
@@ -31,9 +31,10 @@
// version.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
/**
@@ -56,143 +57,113 @@ this.createjs = this.createjs || {};
* @type {String}
* @static
**/
- s.buildDate = /*=date*/"Thu, 22 Oct 2015 16:01:29 GMT"; // injected by build process
+ s.buildDate = /*=date*/"Wed, 02 Dec 2015 18:53:18 GMT"; // injected by build process
-})();
+})(scope.createjs);
//##############################################################################
// extend.js
//##############################################################################
-this.createjs = this.createjs||{};
-
-/**
- * @class Utility Methods
- */
-
-/**
- * Sets up the prototype chain and constructor property for a new class.
- *
- * This should be called right after creating the class constructor.
- *
- * function MySubClass() {}
- * createjs.extend(MySubClass, MySuperClass);
- * ClassB.prototype.doSomething = function() { }
- *
- * var foo = new MySubClass();
- * console.log(foo instanceof MySuperClass); // true
- * console.log(foo.prototype.constructor === MySubClass); // true
- *
- * @method extend
- * @param {Function} subclass The subclass.
- * @param {Function} superclass The superclass to extend.
- * @return {Function} Returns the subclass's new prototype.
- */
-createjs.extend = function(subclass, superclass) {
- "use strict";
-
- function o() { this.constructor = subclass; }
- o.prototype = superclass.prototype;
- return (subclass.prototype = new o());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+/**
+ * @class Utility Methods
+ */
+
+/**
+ * Sets up the prototype chain and constructor property for a new class.
+ *
+ * This should be called right after creating the class constructor.
+ *
+ * function MySubClass() {}
+ * createjs.extend(MySubClass, MySuperClass);
+ * ClassB.prototype.doSomething = function() { }
+ *
+ * var foo = new MySubClass();
+ * console.log(foo instanceof MySuperClass); // true
+ * console.log(foo.prototype.constructor === MySubClass); // true
+ *
+ * @method extend
+ * @param {Function} subclass The subclass.
+ * @param {Function} superclass The superclass to extend.
+ * @return {Function} Returns the subclass's new prototype.
+ */
+scope.createjs.extend = function(subclass, superclass) {
+ "use strict";
+
+ function o() { this.constructor = subclass; }
+ o.prototype = superclass.prototype;
+ return (subclass.prototype = new o());
};
//##############################################################################
// promote.js
//##############################################################################
-this.createjs = this.createjs||{};
-
-/**
- * @class Utility Methods
- */
-
-/**
- * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`.
- * It is recommended to use the super class's name as the prefix.
- * An alias to the super class's constructor is always added in the format `prefix_constructor`.
- * This allows the subclass to call super class methods without using `function.call`, providing better performance.
- *
- * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")`
- * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the
- * prototype of `MySubClass` as `MySuperClass_draw`.
- *
- * This should be called after the class's prototype is fully defined.
- *
- * function ClassA(name) {
- * this.name = name;
- * }
- * ClassA.prototype.greet = function() {
- * return "Hello "+this.name;
- * }
- *
- * function ClassB(name, punctuation) {
- * this.ClassA_constructor(name);
- * this.punctuation = punctuation;
- * }
- * createjs.extend(ClassB, ClassA);
- * ClassB.prototype.greet = function() {
- * return this.ClassA_greet()+this.punctuation;
- * }
- * createjs.promote(ClassB, "ClassA");
- *
- * var foo = new ClassB("World", "!?!");
- * console.log(foo.greet()); // Hello World!?!
- *
- * @method promote
- * @param {Function} subclass The class to promote super class methods on.
- * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass.
- * @return {Function} Returns the subclass.
- */
-createjs.promote = function(subclass, prefix) {
- "use strict";
-
- var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__;
- if (supP) {
- subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable
- for (var n in supP) {
- if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; }
- }
- }
- return subclass;
-};
-
-//##############################################################################
-// indexOf.js
-//##############################################################################
-
-this.createjs = this.createjs||{};
-
-/**
- * @class Utility Methods
- */
-
-/**
- * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of
- * that value. Returns -1 if value is not found.
- *
- * var i = createjs.indexOf(myArray, myElementToFind);
- *
- * @method indexOf
- * @param {Array} array Array to search for searchElement
- * @param searchElement Element to find in array.
- * @return {Number} The first index of searchElement in array.
- */
-createjs.indexOf = function (array, searchElement){
- "use strict";
-
- for (var i = 0,l=array.length; i < l; i++) {
- if (searchElement === array[i]) {
- return i;
- }
- }
- return -1;
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+/**
+ * @class Utility Methods
+ */
+
+/**
+ * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`.
+ * It is recommended to use the super class's name as the prefix.
+ * An alias to the super class's constructor is always added in the format `prefix_constructor`.
+ * This allows the subclass to call super class methods without using `function.call`, providing better performance.
+ *
+ * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")`
+ * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the
+ * prototype of `MySubClass` as `MySuperClass_draw`.
+ *
+ * This should be called after the class's prototype is fully defined.
+ *
+ * function ClassA(name) {
+ * this.name = name;
+ * }
+ * ClassA.prototype.greet = function() {
+ * return "Hello "+this.name;
+ * }
+ *
+ * function ClassB(name, punctuation) {
+ * this.ClassA_constructor(name);
+ * this.punctuation = punctuation;
+ * }
+ * createjs.extend(ClassB, ClassA);
+ * ClassB.prototype.greet = function() {
+ * return this.ClassA_greet()+this.punctuation;
+ * }
+ * createjs.promote(ClassB, "ClassA");
+ *
+ * var foo = new ClassB("World", "!?!");
+ * console.log(foo.greet()); // Hello World!?!
+ *
+ * @method promote
+ * @param {Function} subclass The class to promote super class methods on.
+ * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass.
+ * @return {Function} Returns the subclass.
+ */
+scope.createjs.promote = function(subclass, prefix) {
+ "use strict";
+
+ var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__;
+ if (supP) {
+ subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable
+ for (var n in supP) {
+ if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; }
+ }
+ }
+ return subclass;
};
//##############################################################################
// proxy.js
//##############################################################################
-this.createjs = this.createjs||{};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
/**
* Various utilities that the CreateJS Suite uses. Utilities are created as separate files, and will be available on the
@@ -206,7 +177,7 @@ this.createjs = this.createjs||{};
* @main Utility Methods
*/
-(function() {
+(function(createjs) {
"use strict";
/**
@@ -238,242 +209,277 @@ this.createjs = this.createjs||{};
};
}
-}());
+}(scope.createjs));
//##############################################################################
-// Event.js
+// indexOf.js
//##############################################################################
-this.createjs = this.createjs||{};
-
-(function() {
- "use strict";
-
-// constructor:
- /**
- * Contains properties and methods shared by all events for use with
- * {{#crossLink "EventDispatcher"}}{{/crossLink}}.
- *
- * Note that Event objects are often reused, so you should never
- * rely on an event object's state outside of the call stack it was received in.
- * @class Event
- * @param {String} type The event type.
- * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
- * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
- * @constructor
- **/
- function Event(type, bubbles, cancelable) {
-
-
- // public properties:
- /**
- * The type of event.
- * @property type
- * @type String
- **/
- this.type = type;
-
- /**
- * The object that generated an event.
- * @property target
- * @type Object
- * @default null
- * @readonly
- */
- this.target = null;
-
- /**
- * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
- * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
- * is generated from childObj, then a listener on parentObj would receive the event with
- * target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
- * @property currentTarget
- * @type Object
- * @default null
- * @readonly
- */
- this.currentTarget = null;
-
- /**
- * For bubbling events, this indicates the current event phase:
- * - capture phase: starting from the top parent to the target
- * - at target phase: currently being dispatched from the target
- * - bubbling phase: from the target to the top parent
- *
- * @property eventPhase
- * @type Number
- * @default 0
- * @readonly
- */
- this.eventPhase = 0;
-
- /**
- * Indicates whether the event will bubble through the display list.
- * @property bubbles
- * @type Boolean
- * @default false
- * @readonly
- */
- this.bubbles = !!bubbles;
-
- /**
- * Indicates whether the default behaviour of this event can be cancelled via
- * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
- * @property cancelable
- * @type Boolean
- * @default false
- * @readonly
- */
- this.cancelable = !!cancelable;
-
- /**
- * The epoch time at which this event was created.
- * @property timeStamp
- * @type Number
- * @default 0
- * @readonly
- */
- this.timeStamp = (new Date()).getTime();
-
- /**
- * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
- * on this event.
- * @property defaultPrevented
- * @type Boolean
- * @default false
- * @readonly
- */
- this.defaultPrevented = false;
-
- /**
- * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
- * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
- * @property propagationStopped
- * @type Boolean
- * @default false
- * @readonly
- */
- this.propagationStopped = false;
-
- /**
- * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
- * on this event.
- * @property immediatePropagationStopped
- * @type Boolean
- * @default false
- * @readonly
- */
- this.immediatePropagationStopped = false;
-
- /**
- * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
- * @property removed
- * @type Boolean
- * @default false
- * @readonly
- */
- this.removed = false;
- }
- var p = Event.prototype;
-
- /**
- * REMOVED. Removed in favor of using `MySuperClass_constructor`.
- * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
- * for details.
- *
- * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
- *
- * @method initialize
- * @protected
- * @deprecated
- */
- // p.initialize = function() {}; // searchable for devs wondering where it is.
-
-
-// public methods:
- /**
- * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true.
- * Mirrors the DOM event standard.
- * @method preventDefault
- **/
- p.preventDefault = function() {
- this.defaultPrevented = this.cancelable&&true;
- };
-
- /**
- * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
- * Mirrors the DOM event standard.
- * @method stopPropagation
- **/
- p.stopPropagation = function() {
- this.propagationStopped = true;
- };
-
- /**
- * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
- * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
- * Mirrors the DOM event standard.
- * @method stopImmediatePropagation
- **/
- p.stopImmediatePropagation = function() {
- this.immediatePropagationStopped = this.propagationStopped = true;
- };
-
- /**
- * Causes the active listener to be removed via removeEventListener();
- *
- * myBtn.addEventListener("click", function(evt) {
- * // do stuff...
- * evt.remove(); // removes this listener.
- * });
- *
- * @method remove
- **/
- p.remove = function() {
- this.removed = true;
- };
-
- /**
- * Returns a clone of the Event instance.
- * @method clone
- * @return {Event} a clone of the Event instance.
- **/
- p.clone = function() {
- return new Event(this.type, this.bubbles, this.cancelable);
- };
-
- /**
- * Provides a chainable shortcut method for setting a number of properties on the instance.
- *
- * @method set
- * @param {Object} props A generic object containing properties to copy to the instance.
- * @return {Event} Returns the instance the method is called on (useful for chaining calls.)
- * @chainable
- */
- p.set = function(props) {
- for (var n in props) { this[n] = props[n]; }
- return this;
- };
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+/**
+ * @class Utility Methods
+ */
+
+/**
+ * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of
+ * that value. Returns -1 if value is not found.
+ *
+ * var i = createjs.indexOf(myArray, myElementToFind);
+ *
+ * @method indexOf
+ * @param {Array} array Array to search for searchElement
+ * @param searchElement Element to find in array.
+ * @return {Number} The first index of searchElement in array.
+ */
+scope.createjs.indexOf = function (array, searchElement){
+ "use strict";
+
+ for (var i = 0,l=array.length; i < l; i++) {
+ if (searchElement === array[i]) {
+ return i;
+ }
+ }
+ return -1;
+};
- /**
- * Returns a string representation of this object.
- * @method toString
- * @return {String} a string representation of the instance.
- **/
- p.toString = function() {
- return "[Event (type="+this.type+")]";
- };
+//##############################################################################
+// Event.js
+//##############################################################################
- createjs.Event = Event;
-}());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function(createjs) {
+ "use strict";
+
+// constructor:
+ /**
+ * Contains properties and methods shared by all events for use with
+ * {{#crossLink "EventDispatcher"}}{{/crossLink}}.
+ *
+ * Note that Event objects are often reused, so you should never
+ * rely on an event object's state outside of the call stack it was received in.
+ * @class Event
+ * @param {String} type The event type.
+ * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
+ * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
+ * @constructor
+ **/
+ function Event(type, bubbles, cancelable) {
+
+
+ // public properties:
+ /**
+ * The type of event.
+ * @property type
+ * @type String
+ **/
+ this.type = type;
+
+ /**
+ * The object that generated an event.
+ * @property target
+ * @type Object
+ * @default null
+ * @readonly
+ */
+ this.target = null;
+
+ /**
+ * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
+ * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
+ * is generated from childObj, then a listener on parentObj would receive the event with
+ * target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
+ * @property currentTarget
+ * @type Object
+ * @default null
+ * @readonly
+ */
+ this.currentTarget = null;
+
+ /**
+ * For bubbling events, this indicates the current event phase:
+ * - capture phase: starting from the top parent to the target
+ * - at target phase: currently being dispatched from the target
+ * - bubbling phase: from the target to the top parent
+ *
+ * @property eventPhase
+ * @type Number
+ * @default 0
+ * @readonly
+ */
+ this.eventPhase = 0;
+
+ /**
+ * Indicates whether the event will bubble through the display list.
+ * @property bubbles
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.bubbles = !!bubbles;
+
+ /**
+ * Indicates whether the default behaviour of this event can be cancelled via
+ * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
+ * @property cancelable
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.cancelable = !!cancelable;
+
+ /**
+ * The epoch time at which this event was created.
+ * @property timeStamp
+ * @type Number
+ * @default 0
+ * @readonly
+ */
+ this.timeStamp = (new Date()).getTime();
+
+ /**
+ * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
+ * on this event.
+ * @property defaultPrevented
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.defaultPrevented = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
+ * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
+ * @property propagationStopped
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.propagationStopped = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
+ * on this event.
+ * @property immediatePropagationStopped
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.immediatePropagationStopped = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
+ * @property removed
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.removed = false;
+ }
+ var p = Event.prototype;
+
+ /**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+ // p.initialize = function() {}; // searchable for devs wondering where it is.
+
+
+// public methods:
+ /**
+ * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method preventDefault
+ **/
+ p.preventDefault = function() {
+ this.defaultPrevented = this.cancelable&&true;
+ };
+
+ /**
+ * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method stopPropagation
+ **/
+ p.stopPropagation = function() {
+ this.propagationStopped = true;
+ };
+
+ /**
+ * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
+ * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method stopImmediatePropagation
+ **/
+ p.stopImmediatePropagation = function() {
+ this.immediatePropagationStopped = this.propagationStopped = true;
+ };
+
+ /**
+ * Causes the active listener to be removed via removeEventListener();
+ *
+ * myBtn.addEventListener("click", function(evt) {
+ * // do stuff...
+ * evt.remove(); // removes this listener.
+ * });
+ *
+ * @method remove
+ **/
+ p.remove = function() {
+ this.removed = true;
+ };
+
+ /**
+ * Returns a clone of the Event instance.
+ * @method clone
+ * @return {Event} a clone of the Event instance.
+ **/
+ p.clone = function() {
+ return new Event(this.type, this.bubbles, this.cancelable);
+ };
+
+ /**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the instance.
+ * @return {Event} Returns the instance the method is called on (useful for chaining calls.)
+ * @chainable
+ */
+ p.set = function(props) {
+ for (var n in props) { this[n] = props[n]; }
+ return this;
+ };
+
+ /**
+ * Returns a string representation of this object.
+ * @method toString
+ * @return {String} a string representation of the instance.
+ **/
+ p.toString = function() {
+ return "[Event (type="+this.type+")]";
+ };
+
+ createjs.Event = Event;
+}(scope.createjs));
//##############################################################################
// ErrorEvent.js
//##############################################################################
-this.createjs = this.createjs||{};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function() {
+(function(createjs) {
"use strict";
/**
@@ -517,36 +523,36 @@ this.createjs = this.createjs||{};
createjs.ErrorEvent = createjs.promote(ErrorEvent, "Event");
-}());
+}(scope.createjs));
//##############################################################################
// EventDispatcher.js
//##############################################################################
-this.createjs = this.createjs||{};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function() {
+(function(createjs) {
"use strict";
-
// constructor:
/**
* EventDispatcher provides methods for managing queues of event listeners and dispatching events.
*
* You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
* EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method.
- *
+ *
* Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the
* DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports
* bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent.
- *
+ *
* EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier
- * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The
+ * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The
* {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to
* {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}.
- *
+ *
* Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}}
- * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also
+ * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also
* includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener.
*
* Example
@@ -568,20 +574,20 @@ this.createjs = this.createjs||{};
* instance.addEventListener("click", function(event) {
* console.log(instance == this); // false, scope is ambiguous.
* });
- *
+ *
* instance.on("click", function(event) {
* console.log(instance == this); // true, "on" uses dispatcher scope by default.
* });
- *
+ *
* If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope.
- *
+ *
*
* @class EventDispatcher
* @constructor
**/
function EventDispatcher() {
-
-
+
+
// private properties:
/**
* @protected
@@ -589,7 +595,7 @@ this.createjs = this.createjs||{};
* @type Object
**/
this._listeners = null;
-
+
/**
* @protected
* @property _captureListeners
@@ -616,10 +622,10 @@ this.createjs = this.createjs||{};
// static public methods:
/**
* Static initializer to mix EventDispatcher methods into a target object or prototype.
- *
+ *
* EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class
* EventDispatcher.initialize(myObject); // add to a specific instance
- *
+ *
* @method initialize
* @static
* @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a
@@ -635,7 +641,7 @@ this.createjs = this.createjs||{};
target._dispatchEvent = p._dispatchEvent;
target.willTrigger = p.willTrigger;
};
-
+
// public methods:
/**
@@ -670,16 +676,16 @@ this.createjs = this.createjs||{};
else { arr.push(listener); }
return listener;
};
-
+
/**
* A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener
* only run once, associate arbitrary data with the listener, and remove the listener.
- *
+ *
* This method works by creating an anonymous wrapper function and subscribing it with addEventListener.
* The created anonymous function is returned for use with .removeEventListener (or .off).
- *
+ *
* Example
- *
+ *
* var listener = myBtn.on("click", handleClick, null, false, {count:3});
* function handleClick(evt, data) {
* data.count -= 1;
@@ -690,7 +696,7 @@ this.createjs = this.createjs||{};
* // alternately: evt.remove();
* }
* }
- *
+ *
* @method on
* @param {String} type The string type of the event.
* @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
@@ -742,7 +748,7 @@ this.createjs = this.createjs||{};
}
}
};
-
+
/**
* A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the
* .on method.
@@ -835,12 +841,12 @@ this.createjs = this.createjs||{};
var listeners = this._listeners, captureListeners = this._captureListeners;
return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type]));
};
-
+
/**
* Indicates whether there is at least one listener for the specified event type on this object or any of its
* ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the
* specified type is dispatched from this object, it will trigger at least one listener.
- *
+ *
* This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire
* event flow for a listener, not just this object.
* @method willTrigger
@@ -880,7 +886,7 @@ this.createjs = this.createjs||{};
try { eventObj.currentTarget = this; } catch (e) {}
try { eventObj.eventPhase = eventPhase; } catch (e) {}
eventObj.removed = false;
-
+
arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
for (var i=0; irequired. The source can either be a
- * string (recommended), or an HTML tag.
- * This can also be an object, but in that case it has to include a type and be handled by a plugin.
- * @property src
- * @type {String}
- * @default null
- */
- this.src = null;
-
- /**
- * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
- * be set manually. This is helpful in cases where a file does not have an extension.
- * @property type
- * @type {String}
- * @default null
- */
- this.type = null;
-
- /**
- * A string identifier which can be used to reference the loaded object. If none is provided, this will be
- * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
- * @property id
- * @type {String}
- * @default null
- */
- this.id = null;
-
- /**
- * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
- * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
- * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
- * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
- * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
- * @property maintainOrder
- * @type {Boolean}
- * @default false
- */
- this.maintainOrder = false;
-
- /**
- * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
- * @property callback
- * @type {String}
- * @default null
- */
- this.callback = null;
-
- /**
- * An arbitrary data object, which is included with the loaded object.
- * @property data
- * @type {Object}
- * @default null
- */
- this.data = null;
-
- /**
- * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
- * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
- * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
- * @property method
- * @type {String}
- * @default get
- */
- this.method = createjs.LoadItem.GET;
-
- /**
- * An object hash of name/value pairs to send to the server.
- * @property values
- * @type {Object}
- * @default null
- */
- this.values = null;
-
- /**
- * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
- * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
- * default headers by including them in your headers object.
- * @property headers
- * @type {Object}
- * @default null
- */
- this.headers = null;
-
- /**
- * Enable credentials for XHR requests.
- * @property withCredentials
- * @type {Boolean}
- * @default false
- */
- this.withCredentials = false;
-
- /**
- * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
- * based files (json, xml, text, css, js).
- * @property mimeType
- * @type {String}
- * @default null
- */
- this.mimeType = null;
-
- /**
- * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
- * @property crossOrigin
- * @type {boolean}
- * @default Anonymous
- */
- this.crossOrigin = null;
-
- /**
- * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
- * (level one) loading, as XHR (level 2) provides its own timeout event.
- * @property loadTimeout
- * @type {Number}
- * @default 8000 (8 seconds)
- */
- this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
- };
-
- var p = LoadItem.prototype = {};
- var s = LoadItem;
-
- /**
- * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
- * (level one) loading, as XHR (level 2) provides its own timeout event.
- * @property LOAD_TIMEOUT_DEFAULT
- * @type {number}
- * @static
- */
- s.LOAD_TIMEOUT_DEFAULT = 8000;
-
- /**
- * Create a LoadItem.
- *
- * - String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
- * - LoadItem instances are returned as-is
- * - Objects are returned with any needed properties added
- *
- * @method create
- * @param {LoadItem|String|Object} value The load item value
- * @returns {LoadItem|Object}
- * @static
- */
- s.create = function (value) {
- if (typeof value == "string") {
- var item = new LoadItem();
- item.src = value;
- return item;
- } else if (value instanceof s) {
- return value;
- } else if (value instanceof Object && value.src) {
- if (value.loadTimeout == null) {
- value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
- }
- return value;
- } else {
- throw new Error("Type not recognized.");
- }
- };
-
- /**
- * Provides a chainable shortcut method for setting a number of properties on the instance.
- *
- * Example
- *
- * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
- *
- * @method set
- * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
- * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
- */
- p.set = function(props) {
- for (var n in props) { this[n] = props[n]; }
- return this;
- };
-
- createjs.LoadItem = s;
-
-}());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ /**
+ * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead,
+ * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A
+ * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the
+ * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}}
+ * @class LoadItem
+ * @constructor
+ * @since 0.6.0
+ */
+ function LoadItem() {
+ /**
+ * The source of the file that is being loaded. This property is required. The source can either be a
+ * string (recommended), or an HTML tag.
+ * This can also be an object, but in that case it has to include a type and be handled by a plugin.
+ * @property src
+ * @type {String}
+ * @default null
+ */
+ this.src = null;
+
+ /**
+ * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
+ * be set manually. This is helpful in cases where a file does not have an extension.
+ * @property type
+ * @type {String}
+ * @default null
+ */
+ this.type = null;
+
+ /**
+ * A string identifier which can be used to reference the loaded object. If none is provided, this will be
+ * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
+ * @property id
+ * @type {String}
+ * @default null
+ */
+ this.id = null;
+
+ /**
+ * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
+ * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
+ * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
+ * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
+ * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
+ * @property maintainOrder
+ * @type {Boolean}
+ * @default false
+ */
+ this.maintainOrder = false;
+
+ /**
+ * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
+ * @property callback
+ * @type {String}
+ * @default null
+ */
+ this.callback = null;
+
+ /**
+ * An arbitrary data object, which is included with the loaded object.
+ * @property data
+ * @type {Object}
+ * @default null
+ */
+ this.data = null;
+
+ /**
+ * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
+ * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
+ * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @property method
+ * @type {String}
+ * @default get
+ */
+ this.method = createjs.LoadItem.GET;
+
+ /**
+ * An object hash of name/value pairs to send to the server.
+ * @property values
+ * @type {Object}
+ * @default null
+ */
+ this.values = null;
+
+ /**
+ * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
+ * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
+ * default headers by including them in your headers object.
+ * @property headers
+ * @type {Object}
+ * @default null
+ */
+ this.headers = null;
+
+ /**
+ * Enable credentials for XHR requests.
+ * @property withCredentials
+ * @type {Boolean}
+ * @default false
+ */
+ this.withCredentials = false;
+
+ /**
+ * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
+ * based files (json, xml, text, css, js).
+ * @property mimeType
+ * @type {String}
+ * @default null
+ */
+ this.mimeType = null;
+
+ /**
+ * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
+ * @property crossOrigin
+ * @type {boolean}
+ * @default Anonymous
+ */
+ this.crossOrigin = null;
+
+ /**
+ * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000 (8 seconds)
+ */
+ this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+ };
+
+ var p = LoadItem.prototype = {};
+ var s = LoadItem;
+
+ /**
+ * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property LOAD_TIMEOUT_DEFAULT
+ * @type {number}
+ * @static
+ */
+ s.LOAD_TIMEOUT_DEFAULT = 8000;
+
+ /**
+ * Create a LoadItem.
+ *
+ * - String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
+ * - LoadItem instances are returned as-is
+ * - Objects are returned with any needed properties added
+ *
+ * @method create
+ * @param {LoadItem|String|Object} value The load item value
+ * @returns {LoadItem|Object}
+ * @static
+ */
+ s.create = function (value) {
+ if (typeof value == "string") {
+ var item = new LoadItem();
+ item.src = value;
+ return item;
+ } else if (value instanceof s) {
+ return value;
+ } else if (value instanceof Object && value.src) {
+ if (value.loadTimeout == null) {
+ value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+ }
+ return value;
+ } else {
+ throw new Error("Type not recognized.");
+ }
+ };
+
+ /**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * Example
+ *
+ * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
+ * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
+ */
+ p.set = function(props) {
+ for (var n in props) { this[n] = props[n]; }
+ return this;
+ };
+
+ createjs.LoadItem = s;
+
+}(scope.createjs));
//##############################################################################
// RequestUtils.js
//##############################################################################
-(function () {
-
- /**
- * Utilities that assist with parsing load items, and determining file types, etc.
- * @class RequestUtils
- */
- var s = {};
-
- /**
- * The Regular Expression used to test file URLS for an absolute path.
- * @property ABSOLUTE_PATH
- * @type {RegExp}
- * @static
- */
- s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
-
- /**
- * The Regular Expression used to test file URLS for a relative path.
- * @property RELATIVE_PATH
- * @type {RegExp}
- * @static
- */
- s.RELATIVE_PATT = (/^[./]*?\//i);
-
- /**
- * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
- * removed.
- * @property EXTENSION_PATT
- * @type {RegExp}
- * @static
- */
- s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
-
- /**
- * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
- *
- * - If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
- * `//networkPath`)
- * - If the path is relative. Relative paths start with `../` or `/path` (or similar)
- * - The file extension. This is determined by the filename with an extension. Query strings are dropped, and
- * the file path is expected to follow the format `name.ext`.
- *
- * @method parseURI
- * @param {String} path
- * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
- * property, which is the lowercase extension.
- * @static
- */
- s.parseURI = function (path) {
- var info = {absolute: false, relative: false};
- if (path == null) { return info; }
-
- // Drop the query string
- var queryIndex = path.indexOf("?");
- if (queryIndex > -1) {
- path = path.substr(0, queryIndex);
- }
-
- // Absolute
- var match;
- if (s.ABSOLUTE_PATT.test(path)) {
- info.absolute = true;
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+
+ /**
+ * Utilities that assist with parsing load items, and determining file types, etc.
+ * @class RequestUtils
+ */
+ var s = {};
+
+ /**
+ * The Regular Expression used to test file URLS for an absolute path.
+ * @property ABSOLUTE_PATH
+ * @type {RegExp}
+ * @static
+ */
+ s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
+
+ /**
+ * The Regular Expression used to test file URLS for a relative path.
+ * @property RELATIVE_PATH
+ * @type {RegExp}
+ * @static
+ */
+ s.RELATIVE_PATT = (/^[./]*?\//i);
+
+ /**
+ * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
+ * removed.
+ * @property EXTENSION_PATT
+ * @type {RegExp}
+ * @static
+ */
+ s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
+
+ /**
+ * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
+ *
+ * - If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
+ * `//networkPath`)
+ * - If the path is relative. Relative paths start with `../` or `/path` (or similar)
+ * - The file extension. This is determined by the filename with an extension. Query strings are dropped, and
+ * the file path is expected to follow the format `name.ext`.
+ *
+ * @method parseURI
+ * @param {String} path
+ * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
+ * property, which is the lowercase extension.
+ * @static
+ */
+ s.parseURI = function (path) {
+ var info = {absolute: false, relative: false};
+ if (path == null) { return info; }
+
+ // Drop the query string
+ var queryIndex = path.indexOf("?");
+ if (queryIndex > -1) {
+ path = path.substr(0, queryIndex);
+ }
+
+ // Absolute
+ var match;
+ if (s.ABSOLUTE_PATT.test(path)) {
+ info.absolute = true;
+
+ // Relative
+ } else if (s.RELATIVE_PATT.test(path)) {
+ info.relative = true;
+ }
+
+ // Extension
+ if (match = path.match(s.EXTENSION_PATT)) {
+ info.extension = match[1].toLowerCase();
+ }
+ return info;
+ };
+
+ /**
+ * Formats an object into a query string for either a POST or GET request.
+ * @method formatQueryString
+ * @param {Object} data The data to convert to a query string.
+ * @param {Array} [query] Existing name/value pairs to append on to this query.
+ * @static
+ */
+ s.formatQueryString = function (data, query) {
+ if (data == null) {
+ throw new Error('You must specify data.');
+ }
+ var params = [];
+ for (var n in data) {
+ params.push(n + '=' + escape(data[n]));
+ }
+ if (query) {
+ params = params.concat(query);
+ }
+ return params.join('&');
+ };
+
+ /**
+ * A utility method that builds a file path using a source and a data object, and formats it into a new path.
+ * @method buildPath
+ * @param {String} src The source path to add values to.
+ * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
+ * path will be preserved.
+ * @returns {string} A formatted string that contains the path and the supplied parameters.
+ * @static
+ */
+ s.buildPath = function (src, data) {
+ if (data == null) {
+ return src;
+ }
+
+ var query = [];
+ var idx = src.indexOf('?');
+
+ if (idx != -1) {
+ var q = src.slice(idx + 1);
+ query = query.concat(q.split('&'));
+ }
+
+ if (idx != -1) {
+ return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
+ } else {
+ return src + '?' + this._formatQueryString(data, query);
+ }
+ };
+
+ /**
+ * @method isCrossDomain
+ * @param {LoadItem|Object} item A load item with a `src` property.
+ * @return {Boolean} If the load item is loading from a different domain than the current location.
+ * @static
+ */
+ s.isCrossDomain = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+
+ var host = document.createElement("a");
+ host.href = location.href;
+
+ var crossdomain = (target.hostname != "") &&
+ (target.port != host.port ||
+ target.protocol != host.protocol ||
+ target.hostname != host.hostname);
+ return crossdomain;
+ };
+
+ /**
+ * @method isLocal
+ * @param {LoadItem|Object} item A load item with a `src` property
+ * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
+ * well.
+ * @static
+ */
+ s.isLocal = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+ return target.hostname == "" && target.protocol == "file:";
+ };
+
+ /**
+ * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
+ * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play
+ * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
+ * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
+ * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @method isBinary
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is binary.
+ * @static
+ */
+ s.isBinary = function (type) {
+ switch (type) {
+ case createjs.AbstractLoader.IMAGE:
+ case createjs.AbstractLoader.BINARY:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * Check if item is a valid HTMLImageElement
+ * @method isImageTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+ s.isImageTag = function(item) {
+ return item instanceof HTMLImageElement;
+ };
+
+ /**
+ * Check if item is a valid HTMLAudioElement
+ * @method isAudioTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+ s.isAudioTag = function(item) {
+ if (window.HTMLAudioElement) {
+ return item instanceof HTMLAudioElement;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Check if item is a valid HTMLVideoElement
+ * @method isVideoTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+ s.isVideoTag = function(item) {
+ if (window.HTMLVideoElement) {
+ return item instanceof HTMLVideoElement;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
+ * @method isText
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is text.
+ * @static
+ */
+ s.isText = function (type) {
+ switch (type) {
+ case createjs.AbstractLoader.TEXT:
+ case createjs.AbstractLoader.JSON:
+ case createjs.AbstractLoader.MANIFEST:
+ case createjs.AbstractLoader.XML:
+ case createjs.AbstractLoader.CSS:
+ case createjs.AbstractLoader.SVG:
+ case createjs.AbstractLoader.JAVASCRIPT:
+ case createjs.AbstractLoader.SPRITESHEET:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
+ * if it is an unusual extension.
+ * @method getTypeByExtension
+ * @param {String} extension The file extension to use to determine the load type.
+ * @return {String} The determined load type (for example, AbstractLoader.IMAGE
). Will return `null` if
+ * the type can not be determined by the extension.
+ * @static
+ */
+ s.getTypeByExtension = function (extension) {
+ if (extension == null) {
+ return createjs.AbstractLoader.TEXT;
+ }
+
+ switch (extension.toLowerCase()) {
+ case "jpeg":
+ case "jpg":
+ case "gif":
+ case "png":
+ case "webp":
+ case "bmp":
+ return createjs.AbstractLoader.IMAGE;
+ case "ogg":
+ case "mp3":
+ case "webm":
+ return createjs.AbstractLoader.SOUND;
+ case "mp4":
+ case "webm":
+ case "ts":
+ return createjs.AbstractLoader.VIDEO;
+ case "json":
+ return createjs.AbstractLoader.JSON;
+ case "xml":
+ return createjs.AbstractLoader.XML;
+ case "css":
+ return createjs.AbstractLoader.CSS;
+ case "js":
+ return createjs.AbstractLoader.JAVASCRIPT;
+ case 'svg':
+ return createjs.AbstractLoader.SVG;
+ default:
+ return createjs.AbstractLoader.TEXT;
+ }
+ };
+
+ createjs.RequestUtils = s;
+
+}(scope.createjs));
- // Relative
- } else if (s.RELATIVE_PATT.test(path)) {
- info.relative = true;
- }
+//##############################################################################
+// AbstractLoader.js
+//##############################################################################
- // Extension
- if (match = path.match(s.EXTENSION_PATT)) {
- info.extension = match[1].toLowerCase();
- }
- return info;
- };
-
- /**
- * Formats an object into a query string for either a POST or GET request.
- * @method formatQueryString
- * @param {Object} data The data to convert to a query string.
- * @param {Array} [query] Existing name/value pairs to append on to this query.
- * @static
- */
- s.formatQueryString = function (data, query) {
- if (data == null) {
- throw new Error('You must specify data.');
- }
- var params = [];
- for (var n in data) {
- params.push(n + '=' + escape(data[n]));
- }
- if (query) {
- params = params.concat(query);
- }
- return params.join('&');
- };
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+// constructor
+ /**
+ * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
+ * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
+ * @class AbstractLoader
+ * @param {LoadItem|object|string} loadItem The item to be loaded.
+ * @param {Boolean} [preferXHR] Determines if the LoadItem should try and load using XHR, or take a
+ * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
+ * other, so this is a suggested directive.
+ * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
+ * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
+ * @extends EventDispatcher
+ */
+ function AbstractLoader(loadItem, preferXHR, type) {
+ this.EventDispatcher_constructor();
+
+ // public properties
+ /**
+ * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
+ * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
+ * @property loaded
+ * @type {Boolean}
+ * @default false
+ */
+ this.loaded = false;
+
+ /**
+ * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
+ * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
+ * instead.
+ * @property canceled
+ * @type {Boolean}
+ * @default false
+ * @readonly
+ */
+ this.canceled = false;
+
+ /**
+ * The current load progress (percentage) for this item. This will be a number between 0 and 1.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.loadFile("largeImage.png");
+ * queue.on("progress", function() {
+ * console.log("Progress:", queue.progress, event.progress);
+ * });
+ *
+ * @property progress
+ * @type {Number}
+ * @default 0
+ */
+ this.progress = 0;
+
+ /**
+ * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
+ * supported types.
+ * @property type
+ * @type {String}
+ */
+ this.type = type;
+
+ /**
+ * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
+ * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
+ * can be overridden to provide custom formatting.
+ *
+ * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
+ * asynchronous, such as creating a new image. The callback function is passed 2 parameters, which are callbacks
+ * to handle success and error conditions in the resultFormatter. Note that the resultFormatter method is
+ * called in the current scope, as well as the success and error callbacks.
+ *
+ * Example asynchronous resultFormatter
+ *
+ * function _formatResult(loader) {
+ * return function(success, error) {
+ * if (errorCondition) { error(errorDetailEvent); }
+ * success(result);
+ * }
+ * }
+ * @property resultFormatter
+ * @type {Function}
+ * @default null
+ */
+ this.resultFormatter = null;
+
+ // protected properties
+ /**
+ * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
+ * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
+ * @property _item
+ * @type {LoadItem|Object}
+ * @private
+ */
+ if (loadItem) {
+ this._item = createjs.LoadItem.create(loadItem);
+ } else {
+ this._item = null;
+ }
+
+ /**
+ * Whether the loader will try and load content using XHR (true) or HTML tags (false).
+ * @property _preferXHR
+ * @type {Boolean}
+ * @private
+ */
+ this._preferXHR = preferXHR;
+
+ /**
+ * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
+ * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
+ * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
+ * @property _result
+ * @type {Object|String}
+ * @private
+ */
+ this._result = null;
+
+ /**
+ * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
+ * method, and passing `true`.
+ * @property _rawResult
+ * @type {Object|String}
+ * @private
+ */
+ this._rawResult = null;
+
+ /**
+ * A list of items that loaders load behind the scenes. This does not include the main item the loader is
+ * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _loadItems
+ * @type {null}
+ * @protected
+ */
+ this._loadedItems = null;
+
+ /**
+ * The attribute the items loaded using tags use for the source.
+ * @type {string}
+ * @default null
+ * @private
+ */
+ this._tagSrcAttribute = null;
+
+ /**
+ * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
+ * @property _tag
+ * @type {Object}
+ * @private
+ */
+ this._tag = null;
+ };
+
+ var p = createjs.extend(AbstractLoader, createjs.EventDispatcher);
+ var s = AbstractLoader;
+
+ // TODO: deprecated
+ // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
+
+
+ /**
+ * Defines a POST request, use for a method value when loading data.
+ * @property POST
+ * @type {string}
+ * @default post
+ * @static
+ */
+ s.POST = "POST";
+
+ /**
+ * Defines a GET request, use for a method value when loading data.
+ * @property GET
+ * @type {string}
+ * @default get
+ * @static
+ */
+ s.GET = "GET";
+
+ /**
+ * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @since 0.6.0
+ */
+ s.BINARY = "binary";
+
+ /**
+ * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a
+ * <style> tag when loaded with tags.
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @since 0.6.0
+ */
+ s.CSS = "css";
+
+ /**
+ * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag.
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @since 0.6.0
+ */
+ s.IMAGE = "image";
+
+ /**
+ * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
+ * <script> tag.
+ *
+ * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
+ * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
+ * only tag-loaded scripts are injected.
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @since 0.6.0
+ */
+ s.JAVASCRIPT = "javascript";
+
+ /**
+ * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
+ * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
+ * must contain a matching wrapper function.
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @since 0.6.0
+ */
+ s.JSON = "json";
+
+ /**
+ * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
+ * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
+ * property is set to.
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @since 0.6.0
+ */
+ s.JSONP = "jsonp";
+
+ /**
+ * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
+ * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
+ * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
+ * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.6.0
+ */
+ s.MANIFEST = "manifest";
+
+ /**
+ * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
+ * <audio> tag.
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @since 0.6.0
+ */
+ s.SOUND = "sound";
+
+ /**
+ * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
+ * <video> tag.
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @since 0.6.0
+ */
+ s.VIDEO = "video";
+
+ /**
+ * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
+ * @property SPRITESHEET
+ * @type {String}
+ * @default spritesheet
+ * @static
+ * @since 0.6.0
+ */
+ s.SPRITESHEET = "spritesheet";
+
+ /**
+ * The preload type for SVG files.
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @since 0.6.0
+ */
+ s.SVG = "svg";
+
+ /**
+ * The preload type for text files, which is also the default file type if the type can not be determined. Text is
+ * loaded as raw text.
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @since 0.6.0
+ */
+ s.TEXT = "text";
+
+ /**
+ * The preload type for xml files. XML is loaded into an XML document.
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @since 0.6.0
+ */
+ s.XML = "xml";
+
+// Events
+ /**
+ * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
+ * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event progress
+ * @since 0.3.0
+ */
+
+ /**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
+ * @event loadstart
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.1
+ */
+
+ /**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
+ * @event complete
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.0
+ */
+
+ /**
+ * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
+ * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
+ * just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event error
+ * @since 0.3.0
+ */
+
+ /**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
+ * This enables loaders to maintain internal queues, and surface file load errors.
+ * @event fileerror
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The even type ("fileerror")
+ * @param {LoadItem|object} The item that encountered the error
+ * @since 0.6.0
+ */
+
+ /**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
+ * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
+ * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
+ * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("fileload")
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.6.0
+ */
+
+ /**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
+ * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
+ * @event initialize
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("initialize")
+ * @param {AbstractLoader} loader The loader that has been initialized.
+ */
+
+
+ /**
+ * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
+ * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
+ * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @method getItem
+ * @return {Object} The manifest item that this loader is responsible for loading.
+ * @since 0.6.0
+ */
+ p.getItem = function () {
+ return this._item;
+ };
+
+ /**
+ * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
+ * event is dispatched.
+ * @method getResult
+ * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
+ * data (if it exists).
+ * @return {Object}
+ * @since 0.6.0
+ */
+ p.getResult = function (raw) {
+ return raw ? this._rawResult : this._result;
+ };
+
+ /**
+ * Return the `tag` this object creates or uses for loading.
+ * @method getTag
+ * @return {Object} The tag instance
+ * @since 0.6.0
+ */
+ p.getTag = function () {
+ return this._tag;
+ };
+
+ /**
+ * Set the `tag` this item uses for loading.
+ * @method setTag
+ * @param {Object} tag The tag instance
+ * @since 0.6.0
+ */
+ p.setTag = function(tag) {
+ this._tag = tag;
+ };
+
+ /**
+ * Begin loading the item. This method is required when using a loader by itself.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.on("complete", handleComplete);
+ * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
+ * queue.load();
+ *
+ * @method load
+ */
+ p.load = function () {
+ this._createRequest();
+
+ this._request.on("complete", this, this);
+ this._request.on("progress", this, this);
+ this._request.on("loadStart", this, this);
+ this._request.on("abort", this, this);
+ this._request.on("timeout", this, this);
+ this._request.on("error", this, this);
+
+ var evt = new createjs.Event("initialize");
+ evt.loader = this._request;
+ this.dispatchEvent(evt);
+
+ this._request.load();
+ };
+
+ /**
+ * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
+ * the background), but events will not longer be dispatched.
+ * @method cancel
+ */
+ p.cancel = function () {
+ this.canceled = true;
+ this.destroy();
+ };
+
+ /**
+ * Clean up the loader.
+ * @method destroy
+ */
+ p.destroy = function() {
+ if (this._request) {
+ this._request.removeAllEventListeners();
+ this._request.destroy();
+ }
+
+ this._request = null;
+
+ this._item = null;
+ this._rawResult = null;
+ this._result = null;
+
+ this._loadItems = null;
+
+ this.removeAllEventListeners();
+ };
+
+ /**
+ * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to expose items it loads internally.
+ * @method getLoadedItems
+ * @return {Array} A list of the items loaded by the loader.
+ * @since 0.6.0
+ */
+ p.getLoadedItems = function () {
+ return this._loadedItems;
+ };
+
+
+ // Private methods
+ /**
+ * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
+ * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
+ * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
+ * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
+ * @method _createRequest
+ * @protected
+ */
+ p._createRequest = function() {
+ if (!this._preferXHR) {
+ this._request = new createjs.TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ } else {
+ this._request = new createjs.XHRRequest(this._item);
+ }
+ };
+
+ /**
+ * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
+ * by loaders that require tag loading.
+ * @method _createTag
+ * @param {String} src The tag source
+ * @return {HTMLElement} The tag that was created
+ * @protected
+ */
+ p._createTag = function(src) { return null; };
+
+ /**
+ * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendLoadStart
+ * @protected
+ */
+ p._sendLoadStart = function () {
+ if (this._isCanceled()) { return; }
+ this.dispatchEvent("loadstart");
+ };
+
+ /**
+ * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
+ * @method _sendProgress
+ * @param {Number | Object} value The progress of the loaded item, or an object containing loaded
+ * and total
properties.
+ * @protected
+ */
+ p._sendProgress = function (value) {
+ if (this._isCanceled()) { return; }
+ var event = null;
+ if (typeof(value) == "number") {
+ this.progress = value;
+ event = new createjs.ProgressEvent(this.progress);
+ } else {
+ event = value;
+ this.progress = value.loaded / value.total;
+ event.progress = this.progress;
+ if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
+ }
+ this.hasEventListener("progress") && this.dispatchEvent(event);
+ };
+
+ /**
+ * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
+ * @method _sendComplete
+ * @protected
+ */
+ p._sendComplete = function () {
+ if (this._isCanceled()) { return; }
+
+ this.loaded = true;
+
+ var event = new createjs.Event("complete");
+ event.rawResult = this._rawResult;
+
+ if (this._result != null) {
+ event.result = this._result;
+ }
+
+ this.dispatchEvent(event);
+ };
+
+ /**
+ * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendError
+ * @param {ErrorEvent} event The event object containing specific error properties.
+ * @protected
+ */
+ p._sendError = function (event) {
+ if (this._isCanceled() || !this.hasEventListener("error")) { return; }
+ if (event == null) {
+ event = new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
+ }
+ this.dispatchEvent(event);
+ };
+
+ /**
+ * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
+ * do not cause issues after the queue has been cleaned up.
+ * @method _isCanceled
+ * @return {Boolean} If the loader has been canceled.
+ * @protected
+ */
+ p._isCanceled = function () {
+ if (window.createjs == null || this.canceled) {
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * A custom result formatter function, which is called just before a request dispatches its complete event. Most
+ * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
+ * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
+ * @property resultFormatter
+ * @type Function
+ * @return {Object} The formatted result
+ * @since 0.6.0
+ */
+ p.resultFormatter = null;
+
+ /**
+ * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
+ * this method can be overridden for custom behaviours.
+ * @method handleEvent
+ * @param {Event} event The event that the internal request dispatches.
+ * @protected
+ * @since 0.6.0
+ */
+ p.handleEvent = function (event) {
+ switch (event.type) {
+ case "complete":
+ this._rawResult = event.target._response;
+ var result = this.resultFormatter && this.resultFormatter(this);
+ if (result instanceof Function) {
+ result.call(this,
+ createjs.proxy(this._resultFormatSuccess, this),
+ createjs.proxy(this._resultFormatFailed, this)
+ );
+ } else {
+ this._result = result || this._rawResult;
+ this._sendComplete();
+ }
+ break;
+ case "progress":
+ this._sendProgress(event);
+ break;
+ case "error":
+ this._sendError(event);
+ break;
+ case "loadstart":
+ this._sendLoadStart();
+ break;
+ case "abort":
+ case "timeout":
+ if (!this._isCanceled()) {
+ this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR"));
+ }
+ break;
+ }
+ };
+
+ /**
+ * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} result The formatted result
+ * @private
+ */
+ p._resultFormatSuccess = function (result) {
+ this._result = result;
+ this._sendComplete();
+ };
+
+ /**
+ * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} error The error event
+ * @private
+ */
+ p._resultFormatFailed = function (event) {
+ this._sendError(event);
+ };
+
+ /**
+ * @method buildPath
+ * @protected
+ * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
+ * instead.
+ */
+ p.buildPath = function (src, data) {
+ return createjs.RequestUtils.buildPath(src, data);
+ };
+
+ /**
+ * @method toString
+ * @return {String} a string representation of the instance.
+ */
+ p.toString = function () {
+ return "[PreloadJS AbstractLoader]";
+ };
+
+ createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher");
+
+}(scope.createjs));
- /**
- * A utility method that builds a file path using a source and a data object, and formats it into a new path.
- * @method buildPath
- * @param {String} src The source path to add values to.
- * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
- * path will be preserved.
- * @returns {string} A formatted string that contains the path and the supplied parameters.
- * @static
- */
- s.buildPath = function (src, data) {
- if (data == null) {
- return src;
- }
+//##############################################################################
+// AbstractMediaLoader.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * The AbstractMediaLoader is a base class that handles some of the shared methods and properties of loaders that
+ * handle HTML media elements, such as Video and Audio.
+ * @class AbstractMediaLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @param {String} type The type of media to load. Usually "video" or "audio".
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function AbstractMediaLoader(loadItem, preferXHR, type) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, type);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "src";
+
+ this.on("initialize", this._updateXHR, this);
+ };
+
+ var p = createjs.extend(AbstractMediaLoader, createjs.AbstractLoader);
+
+ // static properties
+ // public methods
+ p.load = function () {
+ // TagRequest will handle most of this, but Sound / Video need a few custom properties, so just handle them here.
+ if (!this._tag) {
+ this._tag = this._createTag(this._item.src);
+ }
+
+ this._tag.preload = "auto";
+ this._tag.load();
+
+ this.AbstractLoader_load();
+ };
+
+ // protected methods
+ /**
+ * Creates a new tag for loading if it doesn't exist yet.
+ * @method _createTag
+ * @private
+ */
+ p._createTag = function () {};
+
+
+ p._createRequest = function() {
+ if (!this._preferXHR) {
+ this._request = new createjs.MediaTagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ } else {
+ this._request = new createjs.XHRRequest(this._item);
+ }
+ };
+
+ // protected methods
+ /**
+ * Before the item loads, set its mimeType and responseType.
+ * @property _updateXHR
+ * @param {Event} event
+ * @private
+ */
+ p._updateXHR = function (event) {
+ // Only exists for XHR
+ if (event.loader.setResponseType) {
+ event.loader.setResponseType("blob");
+ }
+ };
+
+ /**
+ * The result formatter for media files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLVideoElement|HTMLAudioElement}
+ * @private
+ */
+ p._formatResult = function (loader) {
+ this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler);
+ this._tag.onstalled = null;
+ if (this._preferXHR) {
+ var URL = window.URL || window.webkitURL;
+ var result = loader.getResult(true);
+
+ loader.getTag().src = URL.createObjectURL(result);
+ }
+ return loader.getTag();
+ };
+
+ createjs.AbstractMediaLoader = createjs.promote(AbstractMediaLoader, "AbstractLoader");
+
+}(scope.createjs));
- var query = [];
- var idx = src.indexOf('?');
+//##############################################################################
+// AbstractRequest.js
+//##############################################################################
- if (idx != -1) {
- var q = src.slice(idx + 1);
- query = query.concat(q.split('&'));
- }
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
- if (idx != -1) {
- return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
- } else {
- return src + '?' + this._formatQueryString(data, query);
- }
- };
+(function (createjs) {
+ "use strict";
/**
- * @method isCrossDomain
- * @param {LoadItem|Object} item A load item with a `src` property.
- * @return {Boolean} If the load item is loading from a different domain than the current location.
- * @static
+ * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
+ * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
+ * hood to get data.
+ * @class AbstractRequest
+ * @param {LoadItem} item
+ * @constructor
*/
- s.isCrossDomain = function (item) {
- var target = document.createElement("a");
- target.href = item.src;
-
- var host = document.createElement("a");
- host.href = location.href;
-
- var crossdomain = (target.hostname != "") &&
- (target.port != host.port ||
- target.protocol != host.protocol ||
- target.hostname != host.hostname);
- return crossdomain;
+ var AbstractRequest = function (item) {
+ this._item = item;
};
+ var p = createjs.extend(AbstractRequest, createjs.EventDispatcher);
+
+ // public methods
/**
- * @method isLocal
- * @param {LoadItem|Object} item A load item with a `src` property
- * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
- * well.
- * @static
+ * Begin a load.
+ * @method load
*/
- s.isLocal = function (item) {
- var target = document.createElement("a");
- target.href = item.src;
- return target.hostname == "" && target.protocol == "file:";
- };
+ p.load = function() {};
/**
- * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
- * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play
- * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
- * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
- * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
- * @method isBinary
- * @param {String} type The item type.
- * @return {Boolean} If the specified type is binary.
- * @static
+ * Clean up a request.
+ * @method destroy
*/
- s.isBinary = function (type) {
- switch (type) {
- case createjs.AbstractLoader.IMAGE:
- case createjs.AbstractLoader.BINARY:
- return true;
- default:
- return false;
- }
- };
+ p.destroy = function() {};
/**
- * Check if item is a valid HTMLImageElement
- * @method isImageTag
- * @param {Object} item
- * @returns {Boolean}
- * @static
+ * Cancel an in-progress request.
+ * @method cancel
*/
- s.isImageTag = function(item) {
- return item instanceof HTMLImageElement;
- };
+ p.cancel = function() {};
+
+ createjs.AbstractRequest = createjs.promote(AbstractRequest, "EventDispatcher");
+
+}(scope.createjs));
+
+//##############################################################################
+// TagRequest.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
+ * @class TagRequest
+ * @param {LoadItem} loadItem
+ * @param {HTMLElement} tag
+ * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
+ */
+ function TagRequest(loadItem, tag, srcAttribute) {
+ this.AbstractRequest_constructor(loadItem);
+
+ // protected properties
+ /**
+ * The HTML tag instance that is used to load.
+ * @property _tag
+ * @type {HTMLElement}
+ * @protected
+ */
+ this._tag = tag;
+
+ /**
+ * The tag attribute that specifies the source, such as "src", "href", etc.
+ * @property _tagSrcAttribute
+ * @type {String}
+ * @protected
+ */
+ this._tagSrcAttribute = srcAttribute;
+
+ /**
+ * A method closure used for handling the tag load event.
+ * @property _loadedHandler
+ * @type {Function}
+ * @private
+ */
+ this._loadedHandler = createjs.proxy(this._handleTagComplete, this);
+
+ /**
+ * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
+ * @property _addedToDOM
+ * @type {Boolean}
+ * @private
+ */
+ this._addedToDOM = false;
+
+ /**
+ * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
+ *
+ * @type {null}
+ * @private
+ */
+ this._startTagVisibility = null;
+ };
+
+ var p = createjs.extend(TagRequest, createjs.AbstractRequest);
+
+ // public methods
+ p.load = function () {
+ this._tag.onload = createjs.proxy(this._handleTagComplete, this);
+ this._tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this);
+ this._tag.onerror = createjs.proxy(this._handleError, this);
+
+ var evt = new createjs.Event("initialize");
+ evt.loader = this._tag;
+
+ this.dispatchEvent(evt);
+
+ this._hideTag();
+
+ this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
+
+ this._tag[this._tagSrcAttribute] = this._item.src;
+
+ // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
+ if (this._tag.parentNode == null) {
+ window.document.body.appendChild(this._tag);
+ this._addedToDOM = true;
+ }
+ };
+
+ p.destroy = function() {
+ this._clean();
+ this._tag = null;
+
+ this.AbstractRequest_destroy();
+ };
+
+ // private methods
+ /**
+ * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
+ * and LINK tags), but other cases may exist.
+ * @method _handleReadyStateChange
+ * @private
+ */
+ p._handleReadyStateChange = function () {
+ clearTimeout(this._loadTimeout);
+ // This is strictly for tags in browsers that do not support onload.
+ var tag = this._tag;
+
+ // Complete is for old IE support.
+ if (tag.readyState == "loaded" || tag.readyState == "complete") {
+ this._handleTagComplete();
+ }
+ };
+
+ /**
+ * Handle any error events from the tag.
+ * @method _handleError
+ * @protected
+ */
+ p._handleError = function() {
+ this._clean();
+ this.dispatchEvent("error");
+ };
+
+ /**
+ * Handle the tag's onload callback.
+ * @method _handleTagComplete
+ * @private
+ */
+ p._handleTagComplete = function () {
+ this._rawResult = this._tag;
+ this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;
+
+ this._clean();
+ this._showTag();
+
+ this.dispatchEvent("complete");
+ };
+
+ /**
+ * The tag request has not loaded within the time specified in loadTimeout.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+ p._handleTimeout = function () {
+ this._clean();
+ this.dispatchEvent(new createjs.Event("timeout"));
+ };
+
+ /**
+ * Remove event listeners, but don't destroy the request object
+ * @method _clean
+ * @private
+ */
+ p._clean = function() {
+ this._tag.onload = null;
+ this._tag.onreadystatechange = null;
+ this._tag.onerror = null;
+ if (this._addedToDOM && this._tag.parentNode != null) {
+ this._tag.parentNode.removeChild(this._tag);
+ }
+ clearTimeout(this._loadTimeout);
+ };
+
+ p._hideTag = function() {
+ this._startTagVisibility = this._tag.style.visibility;
+ this._tag.style.visibility = "hidden";
+ };
+
+ p._showTag = function() {
+ this._tag.style.visibility = this._startTagVisibility;
+ };
+
+ /**
+ * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
+ * that is already in a load, but not complete.
+ * @method _handleStalled
+ * @private
+ */
+ p._handleStalled = function () {
+ //Ignore, let the timeout take care of it. Sometimes its not really stopped.
+ };
+
+ createjs.TagRequest = createjs.promote(TagRequest, "AbstractRequest");
+
+}(scope.createjs));
+
+//##############################################################################
+// MediaTagRequest.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+ // constructor
/**
- * Check if item is a valid HTMLAudioElement
- * @method isAudioTag
- * @param {Object} item
- * @returns {Boolean}
- * @static
+ * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio.
+ * @class MediaTagRequest
+ * @param {LoadItem} loadItem
+ * @param {HTMLAudioElement|HTMLVideoElement} tag
+ * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
+ * @constructor
*/
- s.isAudioTag = function(item) {
- if (window.HTMLAudioElement) {
- return item instanceof HTMLAudioElement;
- } else {
- return false;
- }
+ function MediaTagRequest(loadItem, tag, srcAttribute) {
+ this.AbstractRequest_constructor(loadItem);
+
+ // protected properties
+ this._tag = tag;
+ this._tagSrcAttribute = srcAttribute;
+ this._loadedHandler = createjs.proxy(this._handleTagComplete, this);
};
- /**
- * Check if item is a valid HTMLVideoElement
- * @method isVideoTag
- * @param {Object} item
- * @returns {Boolean}
- * @static
- */
- s.isVideoTag = function(item) {
- if (window.HTMLVideoElement) {
- return item instanceof HTMLVideoElement;
- } else {
- return false;
- }
+ var p = createjs.extend(MediaTagRequest, createjs.TagRequest);
+ var s = MediaTagRequest;
+
+ // public methods
+ p.load = function () {
+ var sc = createjs.proxy(this._handleStalled, this);
+ this._stalledCallback = sc;
+
+ var pc = createjs.proxy(this._handleProgress, this);
+ this._handleProgress = pc;
+
+ this._tag.addEventListener("stalled", sc);
+ this._tag.addEventListener("progress", pc);
+
+ // This will tell us when audio is buffered enough to play through, but not when its loaded.
+ // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient.
+ this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event.
+
+ this.TagRequest_load();
};
- /**
- * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
- * @method isText
- * @param {String} type The item type.
- * @return {Boolean} If the specified type is text.
- * @static
- */
- s.isText = function (type) {
- switch (type) {
- case createjs.AbstractLoader.TEXT:
- case createjs.AbstractLoader.JSON:
- case createjs.AbstractLoader.MANIFEST:
- case createjs.AbstractLoader.XML:
- case createjs.AbstractLoader.CSS:
- case createjs.AbstractLoader.SVG:
- case createjs.AbstractLoader.JAVASCRIPT:
- case createjs.AbstractLoader.SPRITESHEET:
- return true;
- default:
- return false;
+ // private methods
+ p._handleReadyStateChange = function () {
+ clearTimeout(this._loadTimeout);
+ // This is strictly for tags in browsers that do not support onload.
+ var tag = this._tag;
+
+ // Complete is for old IE support.
+ if (tag.readyState == "loaded" || tag.readyState == "complete") {
+ this._handleTagComplete();
}
};
+ p._handleStalled = function () {
+ //Ignore, let the timeout take care of it. Sometimes its not really stopped.
+ };
+
/**
- * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
- * if it is an unusual extension.
- * @method getTypeByExtension
- * @param {String} extension The file extension to use to determine the load type.
- * @return {String} The determined load type (for example, AbstractLoader.IMAGE
). Will return `null` if
- * the type can not be determined by the extension.
- * @static
+ * An XHR request has reported progress.
+ * @method _handleProgress
+ * @param {Object} event The XHR progress event.
+ * @private
*/
- s.getTypeByExtension = function (extension) {
- if (extension == null) {
- return createjs.AbstractLoader.TEXT;
+ p._handleProgress = function (event) {
+ if (!event || event.loaded > 0 && event.total == 0) {
+ return; // Sometimes we get no "total", so just ignore the progress event.
}
- switch (extension.toLowerCase()) {
- case "jpeg":
- case "jpg":
- case "gif":
- case "png":
- case "webp":
- case "bmp":
- return createjs.AbstractLoader.IMAGE;
- case "ogg":
- case "mp3":
- case "webm":
- return createjs.AbstractLoader.SOUND;
- case "mp4":
- case "webm":
- case "ts":
- return createjs.AbstractLoader.VIDEO;
- case "json":
- return createjs.AbstractLoader.JSON;
- case "xml":
- return createjs.AbstractLoader.XML;
- case "css":
- return createjs.AbstractLoader.CSS;
- case "js":
- return createjs.AbstractLoader.JAVASCRIPT;
- case 'svg':
- return createjs.AbstractLoader.SVG;
- default:
- return createjs.AbstractLoader.TEXT;
- }
+ var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
+ this.dispatchEvent(newEvent);
+ };
+
+ // protected methods
+ p._clean = function () {
+ this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler);
+ this._tag.removeEventListener("stalled", this._stalledCallback);
+ this._tag.removeEventListener("progress", this._progressCallback);
+
+ this.TagRequest__clean();
};
- createjs.RequestUtils = s;
+ createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest");
-}());
+}(scope.createjs));
//##############################################################################
-// AbstractLoader.js
+// XHRRequest.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
/**
- * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
- * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
- * @class AbstractLoader
- * @param {LoadItem|object|string} loadItem The item to be loaded.
- * @param {Boolean} [preferXHR] Determines if the LoadItem should try and load using XHR, or take a
- * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
- * other, so this is a suggested directive.
- * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
- * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
- * @extends EventDispatcher
+ * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
+ * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
+ * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
+ * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
+ * cross-domain loading.
+ * @class XHRRequest
+ * @constructor
+ * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * for an overview of supported file properties.
+ * @extends AbstractLoader
*/
- function AbstractLoader(loadItem, preferXHR, type) {
- this.EventDispatcher_constructor();
+ function XHRRequest (item) {
+ this.AbstractRequest_constructor(item);
- // public properties
+ // protected properties
/**
- * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
- * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
- * @property loaded
- * @type {Boolean}
- * @default false
- */
- this.loaded = false;
-
- /**
- * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
- * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
- * instead.
- * @property canceled
- * @type {Boolean}
- * @default false
- * @readonly
+ * A reference to the XHR request used to load the content.
+ * @property _request
+ * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
+ * @private
*/
- this.canceled = false;
+ this._request = null;
/**
- * The current load progress (percentage) for this item. This will be a number between 0 and 1.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.loadFile("largeImage.png");
- * queue.on("progress", function() {
- * console.log("Progress:", queue.progress, event.progress);
- * });
- *
- * @property progress
+ * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
+ * typically IE9).
+ * @property _loadTimeout
* @type {Number}
- * @default 0
- */
- this.progress = 0;
-
- /**
- * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
- * supported types.
- * @property type
- * @type {String}
- */
- this.type = type;
-
- /**
- * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
- * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
- * can be overridden to provide custom formatting.
- *
- * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
- * asynchronous, such as creating a new image. The callback function is passed 2 parameters, which are callbacks
- * to handle success and error conditions in the resultFormatter. Note that the resultFormatter method is
- * called in the current scope, as well as the success and error callbacks.
- *
- * Example asynchronous resultFormatter
- *
- * function _formatResult(loader) {
- * return function(success, error) {
- * if (errorCondition) { error(errorDetailEvent); }
- * success(result);
- * }
- * }
- * @property resultFormatter
- * @type {Function}
- * @default null
- */
- this.resultFormatter = null;
-
- // protected properties
- /**
- * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
- * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
- * @property _item
- * @type {LoadItem|Object}
* @private
*/
- if (loadItem) {
- this._item = createjs.LoadItem.create(loadItem);
- } else {
- this._item = null;
- }
+ this._loadTimeout = null;
/**
- * Whether the loader will try and load content using XHR (true) or HTML tags (false).
- * @property _preferXHR
- * @type {Boolean}
+ * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
+ * the version, so we use capabilities to make a best guess.
+ * @property _xhrLevel
+ * @type {Number}
+ * @default 1
* @private
*/
- this._preferXHR = preferXHR;
+ this._xhrLevel = 1;
/**
- * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
- * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
- * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
- * @property _result
- * @type {Object|String}
+ * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
+ * null until the file is loaded.
+ * @property _response
+ * @type {mixed}
* @private
*/
- this._result = null;
+ this._response = null;
/**
- * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
- * method, and passing `true`.
- * @property _rawResult
- * @type {Object|String}
+ * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
+ * an HTML tag or a formatted object which is set to the result
property, but the developer may still
+ * want to access the raw content as it was loaded.
+ * @property _rawResponse
+ * @type {String|Object}
* @private
*/
- this._rawResult = null;
+ this._rawResponse = null;
- /**
- * A list of items that loaders load behind the scenes. This does not include the main item the loader is
- * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
- * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
- * @property _loadItems
- * @type {null}
- * @protected
- */
- this._loadedItems = null;
+ this._canceled = false;
- /**
- * The attribute the items loaded using tags use for the source.
- * @type {string}
- * @default null
- * @private
- */
- this._tagSrcAttribute = null;
+ // Setup our event handlers now.
+ this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this);
+ this._handleProgressProxy = createjs.proxy(this._handleProgress, this);
+ this._handleAbortProxy = createjs.proxy(this._handleAbort, this);
+ this._handleErrorProxy = createjs.proxy(this._handleError, this);
+ this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this);
+ this._handleLoadProxy = createjs.proxy(this._handleLoad, this);
+ this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this);
- /**
- * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
- * @property _tag
- * @type {Object}
- * @private
- */
- this._tag = null;
+ if (!this._createXHR(item)) {
+ //TODO: Throw error?
+ }
};
- var p = createjs.extend(AbstractLoader, createjs.EventDispatcher);
- var s = AbstractLoader;
-
- // TODO: deprecated
- // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
-
+ var p = createjs.extend(XHRRequest, createjs.AbstractRequest);
+// static properties
/**
- * Defines a POST request, use for a method value when loading data.
- * @property POST
- * @type {string}
- * @default post
- * @static
+ * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
+ * @property ACTIVEX_VERSIONS
+ * @type {Array}
+ * @since 0.4.2
+ * @private
*/
- s.POST = "POST";
+ XHRRequest.ACTIVEX_VERSIONS = [
+ "Msxml2.XMLHTTP.6.0",
+ "Msxml2.XMLHTTP.5.0",
+ "Msxml2.XMLHTTP.4.0",
+ "MSXML2.XMLHTTP.3.0",
+ "MSXML2.XMLHTTP",
+ "Microsoft.XMLHTTP"
+ ];
+// Public methods
/**
- * Defines a GET request, use for a method value when loading data.
- * @property GET
- * @type {string}
- * @default get
- * @static
+ * Look up the loaded result.
+ * @method getResult
+ * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the
+ * HTML head.
+ * - A style tag for CSS (<style />)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - An binary arraybuffer loaded by XHR
+ *
+ * Note that if a raw result is requested, but not found, the result will be returned instead.
*/
- s.GET = "GET";
+ p.getResult = function (raw) {
+ if (raw && this._rawResponse) {
+ return this._rawResponse;
+ }
+ return this._response;
+ };
- /**
- * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
- * @property BINARY
- * @type {String}
- * @default binary
- * @static
- * @since 0.6.0
- */
- s.BINARY = "binary";
+ // Overrides abstract method in AbstractRequest
+ p.cancel = function () {
+ this.canceled = true;
+ this._clean();
+ this._request.abort();
+ };
- /**
- * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a
- * <style> tag when loaded with tags.
- * @property CSS
- * @type {String}
- * @default css
- * @static
- * @since 0.6.0
- */
- s.CSS = "css";
+ // Overrides abstract method in AbstractLoader
+ p.load = function () {
+ if (this._request == null) {
+ this._handleError();
+ return;
+ }
+
+ //Events
+ if (this._request.addEventListener != null) {
+ this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
+ this._request.addEventListener("progress", this._handleProgressProxy, false);
+ this._request.addEventListener("abort", this._handleAbortProxy, false);
+ this._request.addEventListener("error", this._handleErrorProxy, false);
+ this._request.addEventListener("timeout", this._handleTimeoutProxy, false);
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.addEventListener("load", this._handleLoadProxy, false);
+ this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
+ } else {
+ // IE9 support
+ this._request.onloadstart = this._handleLoadStartProxy;
+ this._request.onprogress = this._handleProgressProxy;
+ this._request.onabort = this._handleAbortProxy;
+ this._request.onerror = this._handleErrorProxy;
+ this._request.ontimeout = this._handleTimeoutProxy;
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.onload = this._handleLoadProxy;
+ this._request.onreadystatechange = this._handleReadyStateChangeProxy;
+ }
+
+ // Set up a timeout if we don't have XHR2
+ if (this._xhrLevel == 1) {
+ this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
+ }
+
+ // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome
+ try {
+ if (!this._item.values || this._item.method == createjs.AbstractLoader.GET) {
+ this._request.send();
+ } else if (this._item.method == createjs.AbstractLoader.POST) {
+ this._request.send(createjs.RequestUtils.formatQueryString(this._item.values));
+ }
+ } catch (error) {
+ this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND", null, error));
+ }
+ };
+
+ p.setResponseType = function (type) {
+ // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
+ if (type === 'blob') {
+ type = window.URL ? 'blob' : 'arraybuffer';
+ this._responseType = type;
+ }
+ this._request.responseType = type;
+ };
/**
- * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag.
- * @property IMAGE
- * @type {String}
- * @default image
- * @static
- * @since 0.6.0
+ * Get all the response headers from the XmlHttpRequest.
+ *
+ * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match
+ * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
+ * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
+ * pair.
+ * @method getAllResponseHeaders
+ * @return {String}
+ * @since 0.4.1
*/
- s.IMAGE = "image";
+ p.getAllResponseHeaders = function () {
+ if (this._request.getAllResponseHeaders instanceof Function) {
+ return this._request.getAllResponseHeaders();
+ } else {
+ return null;
+ }
+ };
/**
- * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
- * <script> tag.
+ * Get a specific response header from the XmlHttpRequest.
*
- * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
- * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
- * only tag-loaded scripts are injected.
- * @property JAVASCRIPT
- * @type {String}
- * @default javascript
- * @static
- * @since 0.6.0
+ * From the docs: Returns the header field value from the response of which the field name matches
+ * header, unless the field name is Set-Cookie or Set-Cookie2.
+ * @method getResponseHeader
+ * @param {String} header The header name to retrieve.
+ * @return {String}
+ * @since 0.4.1
*/
- s.JAVASCRIPT = "javascript";
+ p.getResponseHeader = function (header) {
+ if (this._request.getResponseHeader instanceof Function) {
+ return this._request.getResponseHeader(header);
+ } else {
+ return null;
+ }
+ };
+// protected methods
/**
- * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
- * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
- * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
- * must contain a matching wrapper function.
- * @property JSON
- * @type {String}
- * @default json
- * @static
- * @since 0.6.0
+ * The XHR request has reported progress.
+ * @method _handleProgress
+ * @param {Object} event The XHR progress event.
+ * @private
*/
- s.JSON = "json";
+ p._handleProgress = function (event) {
+ if (!event || event.loaded > 0 && event.total == 0) {
+ return; // Sometimes we get no "total", so just ignore the progress event.
+ }
+
+ var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
+ this.dispatchEvent(newEvent);
+ };
/**
- * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
- * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
- * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
- * property is set to.
- * @property JSONP
- * @type {String}
- * @default jsonp
- * @static
- * @since 0.6.0
+ * The XHR request has reported a load start.
+ * @method _handleLoadStart
+ * @param {Object} event The XHR loadStart event.
+ * @private
*/
- s.JSONP = "jsonp";
+ p._handleLoadStart = function (event) {
+ clearTimeout(this._loadTimeout);
+ this.dispatchEvent("loadstart");
+ };
/**
- * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
- * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
- * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
- * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
- * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
- * @property MANIFEST
- * @type {String}
- * @default manifest
- * @static
- * @since 0.6.0
+ * The XHR request has reported an abort event.
+ * @method handleAbort
+ * @param {Object} event The XHR abort event.
+ * @private
*/
- s.MANIFEST = "manifest";
+ p._handleAbort = function (event) {
+ this._clean();
+ this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED", null, event));
+ };
/**
- * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
- * <audio> tag.
- * @property SOUND
- * @type {String}
- * @default sound
- * @static
- * @since 0.6.0
+ * The XHR request has reported an error event.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
*/
- s.SOUND = "sound";
+ p._handleError = function (event) {
+ this._clean();
+ this.dispatchEvent(new createjs.ErrorEvent(event.message));
+ };
/**
- * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
- * <video> tag.
- * @property VIDEO
- * @type {String}
- * @default video
- * @static
- * @since 0.6.0
- */
- s.VIDEO = "video";
-
- /**
- * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
- * @property SPRITESHEET
- * @type {String}
- * @default spritesheet
- * @static
- * @since 0.6.0
- */
- s.SPRITESHEET = "spritesheet";
-
- /**
- * The preload type for SVG files.
- * @property SVG
- * @type {String}
- * @default svg
- * @static
- * @since 0.6.0
- */
- s.SVG = "svg";
-
- /**
- * The preload type for text files, which is also the default file type if the type can not be determined. Text is
- * loaded as raw text.
- * @property TEXT
- * @type {String}
- * @default text
- * @static
- * @since 0.6.0
- */
- s.TEXT = "text";
-
- /**
- * The preload type for xml files. XML is loaded into an XML document.
- * @property XML
- * @type {String}
- * @default xml
- * @static
- * @since 0.6.0
- */
- s.XML = "xml";
-
-// Events
- /**
- * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
- * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
- * @event progress
- * @since 0.3.0
- */
-
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
- * @event loadstart
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type.
- * @since 0.3.1
+ * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
+ * event, so we must monitor the readyStateChange to determine if the file is loaded.
+ * @method _handleReadyStateChange
+ * @param {Object} event The XHR readyStateChange event.
+ * @private
*/
+ p._handleReadyStateChange = function (event) {
+ if (this._request.readyState == 4) {
+ this._handleLoad();
+ }
+ };
/**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
- * @event complete
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type.
- * @since 0.3.0
+ * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
+ * request.readyState == 4
. Only the first call to this method will be processed.
+ * @method _handleLoad
+ * @param {Object} event The XHR load event.
+ * @private
*/
+ p._handleLoad = function (event) {
+ if (this.loaded) {
+ return;
+ }
+ this.loaded = true;
- /**
- * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
- * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
- * just a regular {{#crossLink "Event"}}{{/crossLink}}.
- * @event error
- * @since 0.3.0
- */
+ var error = this._checkError();
+ if (error) {
+ this._handleError(error);
+ return;
+ }
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
- * This enables loaders to maintain internal queues, and surface file load errors.
- * @event fileerror
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The even type ("fileerror")
- * @param {LoadItem|object} The item that encountered the error
- * @since 0.6.0
- */
+ this._response = this._getResponse();
+ // Convert arraybuffer back to blob
+ if (this._responseType === 'arraybuffer') {
+ try {
+ this._response = new Blob([this._response]);
+ } catch (e) {
+ // Fallback to use BlobBuilder if Blob constructor is not supported
+ // Tested on Android 2.3 ~ 4.2 and iOS5 safari
+ window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ if (e.name === 'TypeError' && window.BlobBuilder) {
+ var builder = new BlobBuilder();
+ builder.append(this._response);
+ this._response = builder.getBlob();
+ }
+ }
+ }
+ this._clean();
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
- * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
- * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
- * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
- * @event fileload
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type ("fileload")
- * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
- * object will contain that value as a `src` property.
- * @param {Object} result The HTML tag or parsed result of the loaded item.
- * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
- * to a usable object.
- * @since 0.6.0
- */
+ this.dispatchEvent(new createjs.Event("complete"));
+ };
/**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
- * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
- * @event initialize
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type ("initialize")
- * @param {AbstractLoader} loader The loader that has been initialized.
+ * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout
+ * callback.
+ * @method _handleTimeout
+ * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
+ * @private
*/
+ p._handleTimeout = function (event) {
+ this._clean();
-
- /**
- * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
- * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
- * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
- * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
- * @method getItem
- * @return {Object} The manifest item that this loader is responsible for loading.
- * @since 0.6.0
- */
- p.getItem = function () {
- return this._item;
+ this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT", null, event));
};
+// Protected
/**
- * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
- * event is dispatched.
- * @method getResult
- * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
- * data (if it exists).
- * @return {Object}
- * @since 0.6.0
+ * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
+ * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
+ * @method _checkError
+ * @return {int} If the request status returns an error code.
+ * @private
*/
- p.getResult = function (raw) {
- return raw ? this._rawResult : this._result;
- };
+ p._checkError = function () {
+ //LM: Probably need additional handlers here, maybe 501
+ var status = parseInt(this._request.status);
- /**
- * Return the `tag` this object creates or uses for loading.
- * @method getTag
- * @return {Object} The tag instance
- * @since 0.6.0
- */
- p.getTag = function () {
- return this._tag;
+ switch (status) {
+ case 404: // Not Found
+ case 0: // Not Loaded
+ return new Error(status);
+ }
+ return null;
};
/**
- * Set the `tag` this item uses for loading.
- * @method setTag
- * @param {Object} tag The tag instance
- * @since 0.6.0
+ * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
+ * in other browsers. If there is no response, the _response
property will remain null.
+ * @method _getResponse
+ * @private
*/
- p.setTag = function(tag) {
- this._tag = tag;
- };
+ p._getResponse = function () {
+ if (this._response != null) {
+ return this._response;
+ }
- /**
- * Begin loading the item. This method is required when using a loader by itself.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.on("complete", handleComplete);
- * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
- * queue.load();
- *
- * @method load
- */
- p.load = function () {
- this._createRequest();
+ if (this._request.response != null) {
+ return this._request.response;
+ }
- this._request.on("complete", this, this);
- this._request.on("progress", this, this);
- this._request.on("loadStart", this, this);
- this._request.on("abort", this, this);
- this._request.on("timeout", this, this);
- this._request.on("error", this, this);
+ // Android 2.2 uses .responseText
+ try {
+ if (this._request.responseText != null) {
+ return this._request.responseText;
+ }
+ } catch (e) {
+ }
- var evt = new createjs.Event("initialize");
- evt.loader = this._request;
- this.dispatchEvent(evt);
+ // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
+ try {
+ if (this._request.responseXML != null) {
+ return this._request.responseXML;
+ }
+ } catch (e) {
+ }
- this._request.load();
+ return null;
};
/**
- * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
- * the background), but events will not longer be dispatched.
- * @method cancel
+ * Create an XHR request. Depending on a number of factors, we get totally different results.
+ * - Some browsers get an
XDomainRequest
when loading cross-domain.
+ * - XMLHttpRequest are created when available.
+ * - ActiveX.XMLHTTP objects are used in older IE browsers.
+ * - Text requests override the mime type if possible
+ * - Origin headers are sent for crossdomain requests in some browsers.
+ * - Binary loads set the response type to "arraybuffer"
+ * @method _createXHR
+ * @param {Object} item The requested item that is being loaded.
+ * @return {Boolean} If an XHR request or equivalent was successfully created.
+ * @private
*/
- p.cancel = function () {
- this.canceled = true;
- this.destroy();
- };
+ p._createXHR = function (item) {
+ // Check for cross-domain loads. We can't fully support them, but we can try.
+ var crossdomain = createjs.RequestUtils.isCrossDomain(item);
+ var headers = {};
- /**
- * Clean up the loader.
- * @method destroy
- */
- p.destroy = function() {
- if (this._request) {
- this._request.removeAllEventListeners();
- this._request.destroy();
+ // Create the request. Fallback to whatever support we have.
+ var req = null;
+ if (window.XMLHttpRequest) {
+ req = new XMLHttpRequest();
+ // This is 8 or 9, so use XDomainRequest instead.
+ if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
+ req = new XDomainRequest();
+ }
+ } else { // Old IE versions use a different approach
+ for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
+ var axVersion = s.ACTIVEX_VERSIONS[i];
+ try {
+ req = new ActiveXObject(axVersion);
+ break;
+ } catch (e) {
+ }
+ }
+ if (req == null) {
+ return false;
+ }
}
- this._request = null;
-
- this._item = null;
- this._rawResult = null;
- this._result = null;
-
- this._loadItems = null;
-
- this.removeAllEventListeners();
- };
+ // Default to utf-8 for Text requests.
+ if (item.mimeType == null && createjs.RequestUtils.isText(item.type)) {
+ item.mimeType = "text/plain; charset=utf-8";
+ }
- /**
- * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
- * to expose items it loads internally.
- * @method getLoadedItems
- * @return {Array} A list of the items loaded by the loader.
- * @since 0.6.0
- */
- p.getLoadedItems = function () {
- return this._loadedItems;
- };
+ // IE9 doesn't support overrideMimeType(), so we need to check for it.
+ if (item.mimeType && req.overrideMimeType) {
+ req.overrideMimeType(item.mimeType);
+ }
+ // Determine the XHR level
+ this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;
- // Private methods
- /**
- * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
- * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
- * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
- * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
- * @method _createRequest
- * @protected
- */
- p._createRequest = function() {
- if (!this._preferXHR) {
- this._request = new createjs.TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ var src = null;
+ if (item.method == createjs.AbstractLoader.GET) {
+ src = createjs.RequestUtils.buildPath(item.src, item.values);
} else {
- this._request = new createjs.XHRRequest(this._item);
+ src = item.src;
}
- };
- /**
- * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
- * by loaders that require tag loading.
- * @method _createTag
- * @param {String} src The tag source
- * @return {HTMLElement} The tag that was created
- * @protected
- */
- p._createTag = function(src) { return null; };
+ // Open the request. Set cross-domain flags if it is supported (XHR level 1 only)
+ req.open(item.method || createjs.AbstractLoader.GET, src, true);
- /**
- * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
- * event for details on the event payload.
- * @method _sendLoadStart
- * @protected
- */
- p._sendLoadStart = function () {
- if (this._isCanceled()) { return; }
- this.dispatchEvent("loadstart");
- };
+ if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
+ headers["Origin"] = location.origin;
+ }
- /**
- * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
- * @method _sendProgress
- * @param {Number | Object} value The progress of the loaded item, or an object containing loaded
- * and total
properties.
- * @protected
- */
- p._sendProgress = function (value) {
- if (this._isCanceled()) { return; }
- var event = null;
- if (typeof(value) == "number") {
- this.progress = value;
- event = new createjs.ProgressEvent(this.progress);
- } else {
- event = value;
- this.progress = value.loaded / value.total;
- event.progress = this.progress;
- if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
+ // To send data we need to set the Content-type header)
+ if (item.values && item.method == createjs.AbstractLoader.POST) {
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
}
- this.hasEventListener("progress") && this.dispatchEvent(event);
- };
- /**
- * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
- * @method _sendComplete
- * @protected
- */
- p._sendComplete = function () {
- if (this._isCanceled()) { return; }
+ if (!crossdomain && !headers["X-Requested-With"]) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
- this.loaded = true;
+ if (item.headers) {
+ for (var n in item.headers) {
+ headers[n] = item.headers[n];
+ }
+ }
- var event = new createjs.Event("complete");
- event.rawResult = this._rawResult;
+ for (n in headers) {
+ req.setRequestHeader(n, headers[n])
+ }
- if (this._result != null) {
- event.result = this._result;
+ if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
+ req.withCredentials = item.withCredentials;
}
- this.dispatchEvent(event);
- };
+ this._request = req;
- /**
- * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
- * event for details on the event payload.
- * @method _sendError
- * @param {ErrorEvent} event The event object containing specific error properties.
- * @protected
- */
- p._sendError = function (event) {
- if (this._isCanceled() || !this.hasEventListener("error")) { return; }
- if (event == null) {
- event = new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
- }
- this.dispatchEvent(event);
+ return true;
};
/**
- * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
- * do not cause issues after the queue has been cleaned up.
- * @method _isCanceled
- * @return {Boolean} If the loader has been canceled.
- * @protected
- */
- p._isCanceled = function () {
- if (window.createjs == null || this.canceled) {
- return true;
- }
- return false;
- };
-
- /**
- * A custom result formatter function, which is called just before a request dispatches its complete event. Most
- * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
- * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
- * @property resultFormatter
- * @type Function
- * @return {Object} The formatted result
- * @since 0.6.0
- */
- p.resultFormatter = null;
-
- /**
- * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
- * this method can be overridden for custom behaviours.
- * @method handleEvent
- * @param {Event} event The event that the internal request dispatches.
- * @protected
- * @since 0.6.0
- */
- p.handleEvent = function (event) {
- switch (event.type) {
- case "complete":
- this._rawResult = event.target._response;
- var result = this.resultFormatter && this.resultFormatter(this);
- if (result instanceof Function) {
- result.call(this,
- createjs.proxy(this._resultFormatSuccess, this),
- createjs.proxy(this._resultFormatFailed, this)
- );
- } else {
- this._result = result || this._rawResult;
- this._sendComplete();
- }
- break;
- case "progress":
- this._sendProgress(event);
- break;
- case "error":
- this._sendError(event);
- break;
- case "loadstart":
- this._sendLoadStart();
- break;
- case "abort":
- case "timeout":
- if (!this._isCanceled()) {
- this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR"));
- }
- break;
- }
- };
-
- /**
- * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
- * functions.
- * @method _resultFormatSuccess
- * @param {Object} result The formatted result
- * @private
- */
- p._resultFormatSuccess = function (result) {
- this._result = result;
- this._sendComplete();
- };
-
- /**
- * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
- * functions.
- * @method _resultFormatSuccess
- * @param {Object} error The error event
- * @private
- */
- p._resultFormatFailed = function (event) {
- this._sendError(event);
- };
-
- /**
- * @method buildPath
- * @protected
- * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
- * instead.
- */
- p.buildPath = function (src, data) {
- return createjs.RequestUtils.buildPath(src, data);
- };
-
- /**
- * @method toString
- * @return {String} a string representation of the instance.
- */
- p.toString = function () {
- return "[PreloadJS AbstractLoader]";
- };
-
- createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher");
-
-}());
-
-//##############################################################################
-// AbstractMediaLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * The AbstractMediaLoader is a base class that handles some of the shared methods and properties of loaders that
- * handle HTML media elements, such as Video and Audio.
- * @class AbstractMediaLoader
- * @param {LoadItem|Object} loadItem
- * @param {Boolean} preferXHR
- * @param {String} type The type of media to load. Usually "video" or "audio".
- * @extends AbstractLoader
- * @constructor
- */
- function AbstractMediaLoader(loadItem, preferXHR, type) {
- this.AbstractLoader_constructor(loadItem, preferXHR, type);
-
- // public properties
- this.resultFormatter = this._formatResult;
-
- // protected properties
- this._tagSrcAttribute = "src";
-
- this.on("initialize", this._updateXHR, this);
- };
-
- var p = createjs.extend(AbstractMediaLoader, createjs.AbstractLoader);
-
- // static properties
- // public methods
- p.load = function () {
- // TagRequest will handle most of this, but Sound / Video need a few custom properties, so just handle them here.
- if (!this._tag) {
- this._tag = this._createTag(this._item.src);
- }
-
- this._tag.preload = "auto";
- this._tag.load();
-
- this.AbstractLoader_load();
- };
-
- // protected methods
- /**
- * Creates a new tag for loading if it doesn't exist yet.
- * @method _createTag
+ * A request has completed (or failed or canceled), and needs to be disposed.
+ * @method _clean
* @private
*/
- p._createTag = function () {};
-
+ p._clean = function () {
+ clearTimeout(this._loadTimeout);
- p._createRequest = function() {
- if (!this._preferXHR) {
- this._request = new createjs.MediaTagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ if (this._request.removeEventListener != null) {
+ this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
+ this._request.removeEventListener("progress", this._handleProgressProxy);
+ this._request.removeEventListener("abort", this._handleAbortProxy);
+ this._request.removeEventListener("error", this._handleErrorProxy);
+ this._request.removeEventListener("timeout", this._handleTimeoutProxy);
+ this._request.removeEventListener("load", this._handleLoadProxy);
+ this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
} else {
- this._request = new createjs.XHRRequest(this._item);
- }
- };
-
- // protected methods
- /**
- * Before the item loads, set its mimeType and responseType.
- * @property _updateXHR
- * @param {Event} event
- * @private
- */
- p._updateXHR = function (event) {
- // Only exists for XHR
- if (event.loader.setResponseType) {
- event.loader.setResponseType("blob");
- }
- };
-
- /**
- * The result formatter for media files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {HTMLVideoElement|HTMLAudioElement}
- * @private
- */
- p._formatResult = function (loader) {
- this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler);
- this._tag.onstalled = null;
- if (this._preferXHR) {
- var URL = window.URL || window.webkitURL;
- var result = loader.getResult(true);
-
- loader.getTag().src = URL.createObjectURL(result);
+ this._request.onloadstart = null;
+ this._request.onprogress = null;
+ this._request.onabort = null;
+ this._request.onerror = null;
+ this._request.ontimeout = null;
+ this._request.onload = null;
+ this._request.onreadystatechange = null;
}
- return loader.getTag();
};
- createjs.AbstractMediaLoader = createjs.promote(AbstractMediaLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// AbstractRequest.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- /**
- * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
- * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
- * hood to get data.
- * @class AbstractRequest
- * @param {LoadItem} item
- * @constructor
- */
- var AbstractRequest = function (item) {
- this._item = item;
+ p.toString = function () {
+ return "[PreloadJS XHRRequest]";
};
- var p = createjs.extend(AbstractRequest, createjs.EventDispatcher);
-
- // public methods
- /**
- * Begin a load.
- * @method load
- */
- p.load = function() {};
-
- /**
- * Clean up a request.
- * @method destroy
- */
- p.destroy = function() {};
-
- /**
- * Cancel an in-progress request.
- * @method cancel
- */
- p.cancel = function() {};
-
- createjs.AbstractRequest = createjs.promote(AbstractRequest, "EventDispatcher");
+ createjs.XHRRequest = createjs.promote(XHRRequest, "AbstractRequest");
-}());
+}(scope.createjs));
//##############################################################################
-// TagRequest.js
+// LoadQueue.js
//##############################################################################
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
- * @class TagRequest
- * @param {LoadItem} loadItem
- * @param {HTMLElement} tag
- * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
- */
- function TagRequest(loadItem, tag, srcAttribute) {
- this.AbstractRequest_constructor(loadItem);
-
- // protected properties
- /**
- * The HTML tag instance that is used to load.
- * @property _tag
- * @type {HTMLElement}
- * @protected
- */
- this._tag = tag;
-
- /**
- * The tag attribute that specifies the source, such as "src", "href", etc.
- * @property _tagSrcAttribute
- * @type {String}
- * @protected
- */
- this._tagSrcAttribute = srcAttribute;
-
- /**
- * A method closure used for handling the tag load event.
- * @property _loadedHandler
- * @type {Function}
- * @private
- */
- this._loadedHandler = createjs.proxy(this._handleTagComplete, this);
-
- /**
- * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
- * @property _addedToDOM
- * @type {Boolean}
- * @private
- */
- this._addedToDOM = false;
-
- /**
- * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
- *
- * @type {null}
- * @private
- */
- this._startTagVisibility = null;
- };
-
- var p = createjs.extend(TagRequest, createjs.AbstractRequest);
-
- // public methods
- p.load = function () {
- this._tag.onload = createjs.proxy(this._handleTagComplete, this);
- this._tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this);
- this._tag.onerror = createjs.proxy(this._handleError, this);
-
- var evt = new createjs.Event("initialize");
- evt.loader = this._tag;
-
- this.dispatchEvent(evt);
-
- this._hideTag();
-
- this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
-
- this._tag[this._tagSrcAttribute] = this._item.src;
-
- // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
- if (this._tag.parentNode == null) {
- window.document.body.appendChild(this._tag);
- this._addedToDOM = true;
- }
- };
-
- p.destroy = function() {
- this._clean();
- this._tag = null;
-
- this.AbstractRequest_destroy();
- };
-
- // private methods
- /**
- * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
- * and LINK tags), but other cases may exist.
- * @method _handleReadyStateChange
- * @private
- */
- p._handleReadyStateChange = function () {
- clearTimeout(this._loadTimeout);
- // This is strictly for tags in browsers that do not support onload.
- var tag = this._tag;
-
- // Complete is for old IE support.
- if (tag.readyState == "loaded" || tag.readyState == "complete") {
- this._handleTagComplete();
- }
- };
-
- /**
- * Handle any error events from the tag.
- * @method _handleError
- * @protected
- */
- p._handleError = function() {
- this._clean();
- this.dispatchEvent("error");
- };
-
- /**
- * Handle the tag's onload callback.
- * @method _handleTagComplete
- * @private
- */
- p._handleTagComplete = function () {
- this._rawResult = this._tag;
- this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;
-
- this._clean();
- this._showTag();
-
- this.dispatchEvent("complete");
- };
-
- /**
- * The tag request has not loaded within the time specified in loadTimeout.
- * @method _handleError
- * @param {Object} event The XHR error event.
- * @private
- */
- p._handleTimeout = function () {
- this._clean();
- this.dispatchEvent(new createjs.Event("timeout"));
- };
-
- /**
- * Remove event listeners, but don't destroy the request object
- * @method _clean
- * @private
- */
- p._clean = function() {
- this._tag.onload = null;
- this._tag.onreadystatechange = null;
- this._tag.onerror = null;
- if (this._addedToDOM && this._tag.parentNode != null) {
- this._tag.parentNode.removeChild(this._tag);
- }
- clearTimeout(this._loadTimeout);
- };
-
- p._hideTag = function() {
- this._startTagVisibility = this._tag.style.visibility;
- this._tag.style.visibility = "hidden";
- };
-
- p._showTag = function() {
- this._tag.style.visibility = this._startTagVisibility;
- };
-
- /**
- * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
- * that is already in a load, but not complete.
- * @method _handleStalled
- * @private
- */
- p._handleStalled = function () {
- //Ignore, let the timeout take care of it. Sometimes its not really stopped.
- };
-
- createjs.TagRequest = createjs.promote(TagRequest, "AbstractRequest");
-
-}());
-
-//##############################################################################
-// MediaTagRequest.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio.
- * @class MediaTagRequest
- * @param {LoadItem} loadItem
- * @param {HTMLAudioElement|HTMLVideoElement} tag
- * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
- * @constructor
- */
- function MediaTagRequest(loadItem, tag, srcAttribute) {
- this.AbstractRequest_constructor(loadItem);
-
- // protected properties
- this._tag = tag;
- this._tagSrcAttribute = srcAttribute;
- this._loadedHandler = createjs.proxy(this._handleTagComplete, this);
- };
-
- var p = createjs.extend(MediaTagRequest, createjs.TagRequest);
- var s = MediaTagRequest;
-
- // public methods
- p.load = function () {
- var sc = createjs.proxy(this._handleStalled, this);
- this._stalledCallback = sc;
-
- var pc = createjs.proxy(this._handleProgress, this);
- this._handleProgress = pc;
-
- this._tag.addEventListener("stalled", sc);
- this._tag.addEventListener("progress", pc);
-
- // This will tell us when audio is buffered enough to play through, but not when its loaded.
- // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient.
- this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event.
-
- this.TagRequest_load();
- };
-
- // private methods
- p._handleReadyStateChange = function () {
- clearTimeout(this._loadTimeout);
- // This is strictly for tags in browsers that do not support onload.
- var tag = this._tag;
-
- // Complete is for old IE support.
- if (tag.readyState == "loaded" || tag.readyState == "complete") {
- this._handleTagComplete();
- }
- };
-
- p._handleStalled = function () {
- //Ignore, let the timeout take care of it. Sometimes its not really stopped.
- };
-
- /**
- * An XHR request has reported progress.
- * @method _handleProgress
- * @param {Object} event The XHR progress event.
- * @private
- */
- p._handleProgress = function (event) {
- if (!event || event.loaded > 0 && event.total == 0) {
- return; // Sometimes we get no "total", so just ignore the progress event.
- }
-
- var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
- this.dispatchEvent(newEvent);
- };
-
- // protected methods
- p._clean = function () {
- this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler);
- this._tag.removeEventListener("stalled", this._stalledCallback);
- this._tag.removeEventListener("progress", this._progressCallback);
-
- this.TagRequest__clean();
- };
-
- createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest");
-
-}());
-
-//##############################################################################
-// XHRRequest.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
-// constructor
- /**
- * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
- * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
- * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
- * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
- * cross-domain loading.
- * @class XHRRequest
- * @constructor
- * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * for an overview of supported file properties.
- * @extends AbstractLoader
- */
- function XHRRequest (item) {
- this.AbstractRequest_constructor(item);
-
- // protected properties
- /**
- * A reference to the XHR request used to load the content.
- * @property _request
- * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
- * @private
- */
- this._request = null;
-
- /**
- * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
- * typically IE9).
- * @property _loadTimeout
- * @type {Number}
- * @private
- */
- this._loadTimeout = null;
-
- /**
- * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
- * the version, so we use capabilities to make a best guess.
- * @property _xhrLevel
- * @type {Number}
- * @default 1
- * @private
- */
- this._xhrLevel = 1;
-
- /**
- * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
- * null until the file is loaded.
- * @property _response
- * @type {mixed}
- * @private
- */
- this._response = null;
-
- /**
- * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
- * an HTML tag or a formatted object which is set to the result
property, but the developer may still
- * want to access the raw content as it was loaded.
- * @property _rawResponse
- * @type {String|Object}
- * @private
- */
- this._rawResponse = null;
-
- this._canceled = false;
-
- // Setup our event handlers now.
- this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this);
- this._handleProgressProxy = createjs.proxy(this._handleProgress, this);
- this._handleAbortProxy = createjs.proxy(this._handleAbort, this);
- this._handleErrorProxy = createjs.proxy(this._handleError, this);
- this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this);
- this._handleLoadProxy = createjs.proxy(this._handleLoad, this);
- this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this);
-
- if (!this._createXHR(item)) {
- //TODO: Throw error?
- }
- };
-
- var p = createjs.extend(XHRRequest, createjs.AbstractRequest);
-
-// static properties
- /**
- * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
- * @property ACTIVEX_VERSIONS
- * @type {Array}
- * @since 0.4.2
- * @private
- */
- XHRRequest.ACTIVEX_VERSIONS = [
- "Msxml2.XMLHTTP.6.0",
- "Msxml2.XMLHTTP.5.0",
- "Msxml2.XMLHTTP.4.0",
- "MSXML2.XMLHTTP.3.0",
- "MSXML2.XMLHTTP",
- "Microsoft.XMLHTTP"
- ];
-
-// Public methods
- /**
- * Look up the loaded result.
- * @method getResult
- * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
- * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
- * returned instead.
- * @return {Object} A result object containing the content that was loaded, such as:
- *
- * - An image tag (<image />) for images
- * - A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the
- * HTML head.
- * - A style tag for CSS (<style />)
- * - Raw text for TEXT
- * - A formatted JavaScript object defined by JSON
- * - An XML document
- * - An binary arraybuffer loaded by XHR
- *
- * Note that if a raw result is requested, but not found, the result will be returned instead.
- */
- p.getResult = function (raw) {
- if (raw && this._rawResponse) {
- return this._rawResponse;
- }
- return this._response;
- };
-
- // Overrides abstract method in AbstractRequest
- p.cancel = function () {
- this.canceled = true;
- this._clean();
- this._request.abort();
- };
-
- // Overrides abstract method in AbstractLoader
- p.load = function () {
- if (this._request == null) {
- this._handleError();
- return;
- }
-
- //Events
- if (this._request.addEventListener != null) {
- this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
- this._request.addEventListener("progress", this._handleProgressProxy, false);
- this._request.addEventListener("abort", this._handleAbortProxy, false);
- this._request.addEventListener("error", this._handleErrorProxy, false);
- this._request.addEventListener("timeout", this._handleTimeoutProxy, false);
-
- // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
- this._request.addEventListener("load", this._handleLoadProxy, false);
- this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
- } else {
- // IE9 support
- this._request.onloadstart = this._handleLoadStartProxy;
- this._request.onprogress = this._handleProgressProxy;
- this._request.onabort = this._handleAbortProxy;
- this._request.onerror = this._handleErrorProxy;
- this._request.ontimeout = this._handleTimeoutProxy;
-
- // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
- this._request.onload = this._handleLoadProxy;
- this._request.onreadystatechange = this._handleReadyStateChangeProxy;
- }
-
- // Set up a timeout if we don't have XHR2
- if (this._xhrLevel == 1) {
- this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
- }
-
- // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome
- try {
- if (!this._item.values || this._item.method == createjs.AbstractLoader.GET) {
- this._request.send();
- } else if (this._item.method == createjs.AbstractLoader.POST) {
- this._request.send(createjs.RequestUtils.formatQueryString(this._item.values));
- }
- } catch (error) {
- this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND", null, error));
- }
- };
-
- p.setResponseType = function (type) {
- // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
- if (type === 'blob') {
- type = window.URL ? 'blob' : 'arraybuffer';
- this._responseType = type;
- }
- this._request.responseType = type;
- };
-
- /**
- * Get all the response headers from the XmlHttpRequest.
- *
- * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match
- * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
- * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
- * pair.
- * @method getAllResponseHeaders
- * @return {String}
- * @since 0.4.1
- */
- p.getAllResponseHeaders = function () {
- if (this._request.getAllResponseHeaders instanceof Function) {
- return this._request.getAllResponseHeaders();
- } else {
- return null;
- }
- };
-
- /**
- * Get a specific response header from the XmlHttpRequest.
- *
- * From the docs: Returns the header field value from the response of which the field name matches
- * header, unless the field name is Set-Cookie or Set-Cookie2.
- * @method getResponseHeader
- * @param {String} header The header name to retrieve.
- * @return {String}
- * @since 0.4.1
- */
- p.getResponseHeader = function (header) {
- if (this._request.getResponseHeader instanceof Function) {
- return this._request.getResponseHeader(header);
- } else {
- return null;
- }
- };
-
-// protected methods
- /**
- * The XHR request has reported progress.
- * @method _handleProgress
- * @param {Object} event The XHR progress event.
- * @private
- */
- p._handleProgress = function (event) {
- if (!event || event.loaded > 0 && event.total == 0) {
- return; // Sometimes we get no "total", so just ignore the progress event.
- }
-
- var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
- this.dispatchEvent(newEvent);
- };
-
- /**
- * The XHR request has reported a load start.
- * @method _handleLoadStart
- * @param {Object} event The XHR loadStart event.
- * @private
- */
- p._handleLoadStart = function (event) {
- clearTimeout(this._loadTimeout);
- this.dispatchEvent("loadstart");
- };
-
- /**
- * The XHR request has reported an abort event.
- * @method handleAbort
- * @param {Object} event The XHR abort event.
- * @private
- */
- p._handleAbort = function (event) {
- this._clean();
- this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED", null, event));
- };
-
- /**
- * The XHR request has reported an error event.
- * @method _handleError
- * @param {Object} event The XHR error event.
- * @private
- */
- p._handleError = function (event) {
- this._clean();
- this.dispatchEvent(new createjs.ErrorEvent(event.message));
- };
-
- /**
- * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
- * event, so we must monitor the readyStateChange to determine if the file is loaded.
- * @method _handleReadyStateChange
- * @param {Object} event The XHR readyStateChange event.
- * @private
- */
- p._handleReadyStateChange = function (event) {
- if (this._request.readyState == 4) {
- this._handleLoad();
- }
- };
-
- /**
- * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
- * request.readyState == 4
. Only the first call to this method will be processed.
- * @method _handleLoad
- * @param {Object} event The XHR load event.
- * @private
- */
- p._handleLoad = function (event) {
- if (this.loaded) {
- return;
- }
- this.loaded = true;
-
- var error = this._checkError();
- if (error) {
- this._handleError(error);
- return;
- }
-
- this._response = this._getResponse();
- // Convert arraybuffer back to blob
- if (this._responseType === 'arraybuffer') {
- try {
- this._response = new Blob([this._response]);
- } catch (e) {
- // Fallback to use BlobBuilder if Blob constructor is not supported
- // Tested on Android 2.3 ~ 4.2 and iOS5 safari
- window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
- if (e.name === 'TypeError' && window.BlobBuilder) {
- var builder = new BlobBuilder();
- builder.append(this._response);
- this._response = builder.getBlob();
- }
- }
- }
- this._clean();
-
- this.dispatchEvent(new createjs.Event("complete"));
- };
-
- /**
- * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout
- * callback.
- * @method _handleTimeout
- * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
- * @private
- */
- p._handleTimeout = function (event) {
- this._clean();
-
- this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT", null, event));
- };
-
-// Protected
- /**
- * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
- * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
- * @method _checkError
- * @return {int} If the request status returns an error code.
- * @private
- */
- p._checkError = function () {
- //LM: Probably need additional handlers here, maybe 501
- var status = parseInt(this._request.status);
-
- switch (status) {
- case 404: // Not Found
- case 0: // Not Loaded
- return new Error(status);
- }
- return null;
- };
-
- /**
- * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
- * in other browsers. If there is no response, the _response
property will remain null.
- * @method _getResponse
- * @private
- */
- p._getResponse = function () {
- if (this._response != null) {
- return this._response;
- }
-
- if (this._request.response != null) {
- return this._request.response;
- }
-
- // Android 2.2 uses .responseText
- try {
- if (this._request.responseText != null) {
- return this._request.responseText;
- }
- } catch (e) {
- }
-
- // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
- try {
- if (this._request.responseXML != null) {
- return this._request.responseXML;
- }
- } catch (e) {
- }
-
- return null;
- };
-
- /**
- * Create an XHR request. Depending on a number of factors, we get totally different results.
- * - Some browsers get an
XDomainRequest
when loading cross-domain.
- * - XMLHttpRequest are created when available.
- * - ActiveX.XMLHTTP objects are used in older IE browsers.
- * - Text requests override the mime type if possible
- * - Origin headers are sent for crossdomain requests in some browsers.
- * - Binary loads set the response type to "arraybuffer"
- * @method _createXHR
- * @param {Object} item The requested item that is being loaded.
- * @return {Boolean} If an XHR request or equivalent was successfully created.
- * @private
- */
- p._createXHR = function (item) {
- // Check for cross-domain loads. We can't fully support them, but we can try.
- var crossdomain = createjs.RequestUtils.isCrossDomain(item);
- var headers = {};
-
- // Create the request. Fallback to whatever support we have.
- var req = null;
- if (window.XMLHttpRequest) {
- req = new XMLHttpRequest();
- // This is 8 or 9, so use XDomainRequest instead.
- if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
- req = new XDomainRequest();
- }
- } else { // Old IE versions use a different approach
- for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
- var axVersion = s.ACTIVEX_VERSIONS[i];
- try {
- req = new ActiveXObject(axVersion);
- break;
- } catch (e) {
- }
- }
- if (req == null) {
- return false;
- }
- }
-
- // Default to utf-8 for Text requests.
- if (item.mimeType == null && createjs.RequestUtils.isText(item.type)) {
- item.mimeType = "text/plain; charset=utf-8";
- }
-
- // IE9 doesn't support overrideMimeType(), so we need to check for it.
- if (item.mimeType && req.overrideMimeType) {
- req.overrideMimeType(item.mimeType);
- }
-
- // Determine the XHR level
- this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;
-
- var src = null;
- if (item.method == createjs.AbstractLoader.GET) {
- src = createjs.RequestUtils.buildPath(item.src, item.values);
- } else {
- src = item.src;
- }
-
- // Open the request. Set cross-domain flags if it is supported (XHR level 1 only)
- req.open(item.method || createjs.AbstractLoader.GET, src, true);
-
- if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
- headers["Origin"] = location.origin;
- }
-
- // To send data we need to set the Content-type header)
- if (item.values && item.method == createjs.AbstractLoader.POST) {
- headers["Content-Type"] = "application/x-www-form-urlencoded";
- }
-
- if (!crossdomain && !headers["X-Requested-With"]) {
- headers["X-Requested-With"] = "XMLHttpRequest";
- }
-
- if (item.headers) {
- for (var n in item.headers) {
- headers[n] = item.headers[n];
- }
- }
-
- for (n in headers) {
- req.setRequestHeader(n, headers[n])
- }
-
- if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
- req.withCredentials = item.withCredentials;
- }
-
- this._request = req;
-
- return true;
- };
-
- /**
- * A request has completed (or failed or canceled), and needs to be disposed.
- * @method _clean
- * @private
- */
- p._clean = function () {
- clearTimeout(this._loadTimeout);
-
- if (this._request.removeEventListener != null) {
- this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
- this._request.removeEventListener("progress", this._handleProgressProxy);
- this._request.removeEventListener("abort", this._handleAbortProxy);
- this._request.removeEventListener("error", this._handleErrorProxy);
- this._request.removeEventListener("timeout", this._handleTimeoutProxy);
- this._request.removeEventListener("load", this._handleLoadProxy);
- this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
- } else {
- this._request.onloadstart = null;
- this._request.onprogress = null;
- this._request.onabort = null;
- this._request.onerror = null;
- this._request.ontimeout = null;
- this._request.onload = null;
- this._request.onreadystatechange = null;
- }
- };
-
- p.toString = function () {
- return "[PreloadJS XHRRequest]";
- };
-
- createjs.XHRRequest = createjs.promote(XHRRequest, "AbstractRequest");
-
-}());
-
-//##############################################################################
-// LoadQueue.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-/*
- TODO: WINDOWS ISSUES
- * No error for HTML audio in IE 678
- * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR
- * No script complete handler in IE 67 TAGS (XHR is fine)
- * No XML/JSON in IE6 TAGS
- * Need to hide loading SVG in Opera TAGS
- * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking)
- * SVG no load or failure in Opera XHR
- * Reported issues with IE7/8
- */
-
-(function () {
- "use strict";
-
-// constructor
- /**
- * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either
- * a single file, or queue of files.
- *
- * Creating a Queue
- * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR
- * argument to false.
- *
- * var queue = new createjs.LoadQueue(true);
- *
- * Listening for Events
- * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}}
- * lets you add as many listeners as you want for events. You can subscribe to the following events:
- * - {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all
- * files
- * - {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with
- * any file.
- * - {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has
- * changed.
- * - {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
- * - {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note
- * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
- *
- *
- * queue.on("fileload", handleFileLoad, this);
- * queue.on("complete", handleComplete, this);
- *
- * Adding files and manifests
- * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a
- * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are
- * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you
- * like.
- *
- * queue.loadFile("filePath/file.jpg");
- * queue.loadFile({id:"image", src:"filePath/file.jpg"});
- * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]);
- *
- * // Use an external manifest
- * queue.loadManifest("path/to/manifest.json");
- * queue.loadManifest({src:"manifest.json", type:"manifest"});
- *
- * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not
- * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin
- * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a
- * `loadNow` argument of `true`.
- *
- * queue.load();
- *
- * File Types
- * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS
- * should handle the majority of standard file and url formats, and works with common file extensions. If you have
- * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a
- * type
property with any manifest item.
- *
- * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.AbstractLoader.SOUND});
- *
- * // Note that PreloadJS will not read a file extension from the query string
- * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.AbstractLoader.IMAGE});
- *
- * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
- *
- * - {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
- * - {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files
- * - {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats
- * - {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
- * - {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data
- * - {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
- * - {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see
- * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
- * - {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats
- * - {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This
- * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
- * - {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files
- * - {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only
- * - {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}: Video objects
- * - {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data
- *
- *
- * Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better
- * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but
- * are deprecated.
- *
- * Handling Results
- * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is
- * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a
- * formatted object that can be used immediately, including:
- *
- * - Binary: The binary loaded result
- * - CSS: A <link /> tag
- * - Image: An <img /> tag
- * - JavaScript: A <script /> tag
- * - JSON/JSONP: A formatted JavaScript Object
- * - Manifest: A JavaScript object.
- *
- Sound: An <audio /> tag
- *
- SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images.
- *
- SVG: An <object /> tag
- * - Text: Raw text
- * - Video: A Video DOM node
- * - XML: An XML DOM node
- *
- *
- * function handleFileLoad(event) {
- * var item = event.item; // A reference to the item that was passed in to the LoadQueue
- * var type = item.type;
- *
- * // Add any images to the page body.
- * if (type == createjs.LoadQueue.IMAGE) {
- * document.body.appendChild(event.result);
- * }
- * }
- *
- * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up
- * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the
- * "src" or file path can be used instead, including the `path` defined by a manifest, but not including
- * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content.
- *
- * var image = queue.getResult("image");
- * document.body.appendChild(image);
- *
- * Raw loaded content can be accessed using the rawResult
property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
- * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
- * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
- * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
- *
- * var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
- *
- * Plugins
- * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio,
- * make sure to install the SoundJS Sound class, which will help load HTML audio,
- * Flash audio, and WebAudio files. This should be installed before loading any audio files.
- *
- * queue.installPlugin(createjs.Sound);
- *
- * Known Browser Issues
- *
- * - Browsers without audio support can not load audio files.
- * - Safari on Mac OS X can only play HTML audio if QuickTime is installed
- * - HTML Audio tags will only download until their
canPlayThrough
event is fired. Browsers other
- * than Chrome will continue to download in the background.
- * - When loading scripts using tags, they are automatically added to the document.
- * - Scripts loaded via XHR may not be properly inspectable with browser tools.
- * - IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require
- * XHR to work.
- * - Content loaded via tags will not show progress, and will continue to download in the background when
- * canceled, although no events will be dispatched.
- *
- *
- * @class LoadQueue
- * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP
- * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR
- * when necessary.
- * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue
- * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../`
- * will not receive a base path.
- * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To
- * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any
- * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin
- * parameter is deprecated. Use LoadItem.crossOrigin instead
- *
- * @constructor
- * @extends AbstractLoader
- */
- function LoadQueue (preferXHR, basePath, crossOrigin) {
- this.AbstractLoader_constructor();
-
- /**
- * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}.
- * @property _plugins
- * @type {Array}
- * @private
- * @since 0.6.1
- */
- this._plugins = [];
-
- /**
- * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the
- * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
- * method for more information.
- * @property _typeCallbacks
- * @type {Object}
- * @private
- */
- this._typeCallbacks = {};
-
- /**
- * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the
- * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
- * method for more information.
- * @property _extensionCallbacks
- * @type {null}
- * @private
- */
- this._extensionCallbacks = {};
-
- /**
- * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and
- * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed.
- * @property next
- * @type {LoadQueue}
- * @default null
- */
- this.next = null;
-
- /**
- * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head
- * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas
- * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order
- * specified.
- *
- * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}}
- * property on the load item, or by ensuring that only one connection can be open at a time using
- * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property
- * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the
- * `maintainScriptOrder` to `false` during a load will not change items already in a queue.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.setMaxConnections(3); // Set a higher number to load multiple items at once
- * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order
- * queue.loadManifest([
- * "script1.js",
- * "script2.js",
- * "image.png", // Load any time
- * {src: "image2.png", maintainOrder: true} // Will wait for script2.js
- * "image3.png",
- * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR)
- * ]);
- *
- * @property maintainScriptOrder
- * @type {Boolean}
- * @default true
- */
- this.maintainScriptOrder = true;
-
- /**
- * Determines if the LoadQueue will stop processing the current queue when an error is encountered.
- * @property stopOnError
- * @type {Boolean}
- * @default false
- */
- this.stopOnError = false;
-
- /**
- * The number of maximum open connections that a loadQueue tries to maintain. Please see
- * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information.
- * @property _maxConnections
- * @type {Number}
- * @default 1
- * @private
- */
- this._maxConnections = 1;
-
- /**
- * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the
- * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can
- * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is
- * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the
- * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of
- * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}.
- *
- * Loaders can be removed from PreloadJS by simply not including them.
- *
- * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list
- * so that they are checked first.
- * @property _availableLoaders
- * @type {Array}
- * @private
- * @since 0.6.0
- */
- this._availableLoaders = [
- createjs.ImageLoader,
- createjs.JavaScriptLoader,
- createjs.CSSLoader,
- createjs.JSONLoader,
- createjs.JSONPLoader,
- createjs.SoundLoader,
- createjs.ManifestLoader,
- createjs.SpriteSheetLoader,
- createjs.XMLLoader,
- createjs.SVGLoader,
- createjs.BinaryLoader,
- createjs.VideoLoader,
- createjs.TextLoader
- ];
-
- /**
- * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}.
- * @property _defaultLoaderLength
- * @type {Number}
- * @private
- * @since 0.6.0
- */
- this._defaultLoaderLength = this._availableLoaders.length;
-
- this.init(preferXHR, basePath, crossOrigin);
- }
-
- var p = createjs.extend(LoadQueue, createjs.AbstractLoader);
- var s = LoadQueue;
-
- /**
- * REMOVED. Removed in favor of using `MySuperClass_constructor`.
- * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
- * for details.
- *
- * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
- *
- * @method initialize
- * @protected
- * @deprecated
- */
- // p.initialize = function() {}; // searchable for devs wondering where it is.
-
- /**
- * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue.
- * @method init
- * @param preferXHR
- * @param basePath
- * @param crossOrigin
- * @private
- */
- p.init = function (preferXHR, basePath, crossOrigin) {
-
- // public properties
- /**
- * @property useXHR
- * @type {Boolean}
- * @readonly
- * @default true
- * @deprecated Use preferXHR instead.
- */
- this.useXHR = true;
-
- /**
- * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR
- * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR,
- * and plain text can not be loaded with tags, so it will default the the correct type instead of using the
- * user-defined type.
- * @type {Boolean}
- * @default true
- * @since 0.6.0
- */
- this.preferXHR = true; //TODO: Get/Set
- this._preferXHR = true;
- this.setPreferXHR(preferXHR);
-
- // protected properties
- /**
- * Whether the queue is currently paused or not.
- * @property _paused
- * @type {boolean}
- * @private
- */
- this._paused = false;
-
- /**
- * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The
- * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such
- * as `http://`, or a relative path such as `../`.
- * @property _basePath
- * @type {String}
- * @private
- * @since 0.3.1
- */
- this._basePath = basePath;
-
- /**
- * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded
- * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by
- * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues,
- * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are ""
- * and "Anonymous".
- * @property _crossOrigin
- * @type {String}
- * @default ""
- * @private
- * @since 0.4.1
- */
- this._crossOrigin = crossOrigin;
-
- /**
- * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first
- * file is requested.
- * @property _loadStartWasDispatched
- * @type {Boolean}
- * @default false
- * @private
- */
- this._loadStartWasDispatched = false;
-
- /**
- * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when
- * using a script tag to do preloading.
- * @property _currentlyLoadingScript
- * @type {Boolean}
- * @private
- */
- this._currentlyLoadingScript = null;
-
- /**
- * An array containing the currently downloading files.
- * @property _currentLoads
- * @type {Array}
- * @private
- */
- this._currentLoads = [];
-
- /**
- * An array containing the queued items that have not yet started downloading.
- * @property _loadQueue
- * @type {Array}
- * @private
- */
- this._loadQueue = [];
-
- /**
- * An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
- * @property _loadQueueBackup
- * @type {Array}
- * @private
- */
- this._loadQueueBackup = [];
-
- /**
- * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}}
- * id.
- * @property _loadItemsById
- * @type {Object}
- * @private
- */
- this._loadItemsById = {};
-
- /**
- * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}}
- * source.
- * @property _loadItemsBySrc
- * @type {Object}
- * @private
- */
- this._loadItemsBySrc = {};
-
- /**
- * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
- * @property _loadedResults
- * @type {Object}
- * @private
- */
- this._loadedResults = {};
-
- /**
- * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
- * @property _loadedRawResults
- * @type {Object}
- * @private
- */
- this._loadedRawResults = {};
-
- /**
- * The number of items that have been requested. This helps manage an overall progress without knowing how large
- * the files are before they are downloaded. This does not include items inside of loaders such as the
- * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
- * @property _numItems
- * @type {Number}
- * @default 0
- * @private
- */
- this._numItems = 0;
-
- /**
- * The number of items that have completed loaded. This helps manage an overall progress without knowing how large
- * the files are before they are downloaded.
- * @property _numItemsLoaded
- * @type {Number}
- * @default 0
- * @private
- */
- this._numItemsLoaded = 0;
-
- /**
- * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right
- * order.
- * @property _scriptOrder
- * @type {Array}
- * @private
- */
- this._scriptOrder = [];
-
- /**
- * A list of scripts that have been loaded. Items are added to this list as null
when they are
- * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true
- * once they are complete and have been dispatched.
- * @property _loadedScripts
- * @type {Array}
- * @private
- */
- this._loadedScripts = [];
-
- /**
- * The last progress amount. This is used to suppress duplicate progress events.
- * @property _lastProgress
- * @type {Number}
- * @private
- * @since 0.6.0
- */
- this._lastProgress = NaN;
-
- };
-
-// static properties
- /**
- * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
- * event is dispatched if the timeout is reached before any data is received.
- * @property loadTimeout
- * @type {Number}
- * @default 8000
- * @static
- * @since 0.4.1
- * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
- */
- s.loadTimeout = 8000;
-
- /**
- * The time in milliseconds to assume a load has failed.
- * @property LOAD_TIMEOUT
- * @type {Number}
- * @default 0
- * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
- */
- s.LOAD_TIMEOUT = 0;
-
-// Preload Types
- /**
- * @property BINARY
- * @type {String}
- * @default binary
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
- */
- s.BINARY = createjs.AbstractLoader.BINARY;
-
- /**
- * @property CSS
- * @type {String}
- * @default css
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
- */
- s.CSS = createjs.AbstractLoader.CSS;
-
- /**
- * @property IMAGE
- * @type {String}
- * @default image
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
- */
- s.IMAGE = createjs.AbstractLoader.IMAGE;
-
- /**
- * @property JAVASCRIPT
- * @type {String}
- * @default javascript
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
- */
- s.JAVASCRIPT = createjs.AbstractLoader.JAVASCRIPT;
-
- /**
- * @property JSON
- * @type {String}
- * @default json
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
- */
- s.JSON = createjs.AbstractLoader.JSON;
-
- /**
- * @property JSONP
- * @type {String}
- * @default jsonp
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
- */
- s.JSONP = createjs.AbstractLoader.JSONP;
-
- /**
- * @property MANIFEST
- * @type {String}
- * @default manifest
- * @static
- * @since 0.4.1
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
- */
- s.MANIFEST = createjs.AbstractLoader.MANIFEST;
-
- /**
- * @property SOUND
- * @type {String}
- * @default sound
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
- */
- s.SOUND = createjs.AbstractLoader.SOUND;
-
- /**
- * @property VIDEO
- * @type {String}
- * @default video
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
- */
- s.VIDEO = createjs.AbstractLoader.VIDEO;
-
- /**
- * @property SVG
- * @type {String}
- * @default svg
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
- */
- s.SVG = createjs.AbstractLoader.SVG;
-
- /**
- * @property TEXT
- * @type {String}
- * @default text
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
- */
- s.TEXT = createjs.AbstractLoader.TEXT;
-
- /**
- * @property XML
- * @type {String}
- * @default xml
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
- */
- s.XML = createjs.AbstractLoader.XML;
-
- /**
- * @property POST
- * @type {string}
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
- */
- s.POST = createjs.AbstractLoader.POST;
-
- /**
- * @property GET
- * @type {string}
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
- */
- s.GET = createjs.AbstractLoader.GET;
-
-// events
- /**
- * This event is fired when an individual file has loaded, and been processed.
- * @event fileload
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type.
- * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
- * object will contain that value as a `src` property.
- * @param {Object} result The HTML tag or parsed result of the loaded item.
- * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
- * to a usable object.
- * @since 0.3.0
- */
-
- /**
- * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
- * @event fileprogress
- * @since 0.3.0
- */
-
- /**
- * This event is fired when an individual file starts to load.
- * @event filestart
- * @param {Object} The object that dispatched the event.
- * @param {String} type The event type.
- * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
- * object will contain that value as a property.
- */
-
- /**
- * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from
- * a LoadQueue instance.
- * @event initialize
- * @private
- */
-
-// public methods
- /**
- * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
- * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
- * once, and will be prepended to the list of available loaders.
- * @method registerLoader
- * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
- * @since 0.6.0
- */
- p.registerLoader = function (loader) {
- if (!loader || !loader.canLoadItem) {
- throw new Error("loader is of an incorrect type.");
- } else if (this._availableLoaders.indexOf(loader) != -1) {
- throw new Error("loader already exists."); //LM: Maybe just silently fail here
- }
-
- this._availableLoaders.unshift(loader);
- };
-
- /**
- * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
- * unregistered, the default loaders will always be available.
- * @method unregisterLoader
- * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
- */
- p.unregisterLoader = function (loader) {
- var idx = this._availableLoaders.indexOf(loader);
- if (idx != -1 && idx < this._defaultLoaderLength - 1) {
- this._availableLoaders.splice(idx, 1);
- }
- };
-
- /**
- * @method setUseXHR
- * @param {Boolean} value The new useXHR value to set.
- * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
- * the provided value argument was true.
- * @since 0.3.0
- * @deprecated use the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property, or the
- * {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} method instead.
- */
- p.setUseXHR = function (value) {
- return this.setPreferXHR(value);
- };
-
- /**
- * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
- * fail, or be ignored depending on the browser's capabilities and the load type.
- * @method setPreferXHR
- * @param {Boolean} value
- * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
- * @since 0.6.0
- */
- p.setPreferXHR = function (value) {
- // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
- //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
- this.preferXHR = (value != false && window.XMLHttpRequest != null);
- return this.preferXHR;
- };
-
- /**
- * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
- * content, and allows the queue to be used again.
- * @method removeAll
- * @since 0.3.0
- */
- p.removeAll = function () {
- this.remove();
- };
-
- /**
- * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
- * This also removes internal references to loaded item(s).
- *
- * Example
- *
- * queue.loadManifest([
- * {src:"test.png", id:"png"},
- * {src:"test.jpg", id:"jpg"},
- * {src:"test.mp3", id:"mp3"}
- * ]);
- * queue.remove("png"); // Single item by ID
- * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
- * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
- *
- * @method remove
- * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
- * items, or multiple items as arguments.
- * @since 0.3.0
- */
- p.remove = function (idsOrUrls) {
- var args = null;
-
- if (idsOrUrls && !Array.isArray(idsOrUrls)) {
- args = [idsOrUrls];
- } else if (idsOrUrls) {
- args = idsOrUrls;
- } else if (arguments.length > 0) {
- return;
- }
-
- var itemsWereRemoved = false;
-
- // Destroy everything
- if (!args) {
- this.close();
- for (var n in this._loadItemsById) {
- this._disposeItem(this._loadItemsById[n]);
- }
- this.init(this.preferXHR, this._basePath);
-
- // Remove specific items
- } else {
- while (args.length) {
- var item = args.pop();
- var r = this.getResult(item);
-
- //Remove from the main load Queue
- for (i = this._loadQueue.length - 1; i >= 0; i--) {
- loadItem = this._loadQueue[i].getItem();
- if (loadItem.id == item || loadItem.src == item) {
- this._loadQueue.splice(i, 1)[0].cancel();
- break;
- }
- }
-
- //Remove from the backup queue
- for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
- loadItem = this._loadQueueBackup[i].getItem();
- if (loadItem.id == item || loadItem.src == item) {
- this._loadQueueBackup.splice(i, 1)[0].cancel();
- break;
- }
- }
-
- if (r) {
- this._disposeItem(this.getItem(item));
- } else {
- for (var i = this._currentLoads.length - 1; i >= 0; i--) {
- var loadItem = this._currentLoads[i].getItem();
- if (loadItem.id == item || loadItem.src == item) {
- this._currentLoads.splice(i, 1)[0].cancel();
- itemsWereRemoved = true;
- break;
- }
- }
- }
- }
-
- // If this was called during a load, try to load the next item.
- if (itemsWereRemoved) {
- this._loadNext();
- }
- }
- };
-
- /**
- * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
- * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
- * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
- * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
- * @method reset
- * @since 0.3.0
- */
- p.reset = function () {
- this.close();
- for (var n in this._loadItemsById) {
- this._disposeItem(this._loadItemsById[n]);
- }
-
- //Reset the queue to its start state
- var a = [];
- for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
- a.push(this._loadQueueBackup[i].getItem());
- }
-
- this.loadManifest(a, false);
- };
-
- /**
- * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
- * Currently, only one plugin can exist per type/extension.
- *
- * When a plugin is installed, a getPreloadHandlers()
method will be called on it. For more information
- * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
- * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
- *
- * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
- * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
- * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
- * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
- * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
- * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
- *
- * @method installPlugin
- * @param {Function} plugin The plugin class to install.
- */
- p.installPlugin = function (plugin) {
- if (plugin == null) {
- return;
- }
-
- if (plugin.getPreloadHandlers != null) {
- this._plugins.push(plugin);
- var map = plugin.getPreloadHandlers();
- map.scope = plugin;
-
- if (map.types != null) {
- for (var i = 0, l = map.types.length; i < l; i++) {
- this._typeCallbacks[map.types[i]] = map;
- }
- }
-
- if (map.extensions != null) {
- for (i = 0, l = map.extensions.length; i < l; i++) {
- this._extensionCallbacks[map.extensions[i]] = map;
- }
- }
- }
- };
-
- /**
- * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
- * number of open connections, so any additional connections may remain in a pending state until the browser
- * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
- * is `true`, only one script is loaded at a time due to browser limitations.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.setMaxConnections(10); // Allow 10 concurrent loads
- *
- * @method setMaxConnections
- * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
- * is open at any time.
- */
- p.setMaxConnections = function (value) {
- this._maxConnections = value;
- if (!this._paused && this._loadQueue.length > 0) {
- this._loadNext();
- }
- };
-
- /**
- * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
- * method.
- *
- * Files are always appended to the current queue, so this method can be used multiple times to add files.
- * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
- * @method loadFile
- * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
- *
- * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
- * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
- * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
- * in the background.
- *
- * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
- * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
- * `true`, the queue will resume automatically.
- * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
- * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
- * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
- * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
- * constructor, or a `path` property in a manifest definition.
- */
- p.loadFile = function (file, loadNow, basePath) {
- if (file == null) {
- var event = new createjs.ErrorEvent("PRELOAD_NO_FILE");
- this._sendError(event);
- return;
- }
- this._addItem(file, null, basePath);
-
- if (loadNow !== false) {
- this.setPaused(false);
- } else {
- this.setPaused(true);
- }
- };
-
- /**
- * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
- * The files in the manifest are requested in the same order, but may complete in a different order if the max
- * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
- * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
- * default).
- *
- * Files are always appended to the current queue, so this method can be used multiple times to add files.
- * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
- * @method loadManifest
- * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
- * manifests:
- *
- * - A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
- * which defines the list of files to load, and can optionally contain a "path" property, which will be
- * prepended to each file in the list.
- * - An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
- * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
- * and can optionally contain a "path" property, which will be prepended to each file in the list.
- * - An object which contains a "manifest" property, which defines the list of files to load, and can
- * optionally contain a "path" property, which will be prepended to each file in the list.
- * - An Array of files to load.
- *
- *
- * Each "file" in a manifest can be either:
- *
- * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
- * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
- * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
- * in the background.
- *
- *
- * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
- * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
- * `true`, the queue will resume automatically.
- * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
- * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
- * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
- * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
- * constructor, or a `path` property in a manifest definition.
- */
- p.loadManifest = function (manifest, loadNow, basePath) {
- var fileList = null;
- var path = null;
-
- // Array-based list of items
- if (Array.isArray(manifest)) {
- if (manifest.length == 0) {
- var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");
- this._sendError(event);
- return;
- }
- fileList = manifest;
-
- // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
- } else if (typeof(manifest) === "string") {
- fileList = [
- {
- src: manifest,
- type: s.MANIFEST
- }
- ];
-
- } else if (typeof(manifest) == "object") {
-
- // An object that defines a manifest path
- if (manifest.src !== undefined) {
- if (manifest.type == null) {
- manifest.type = s.MANIFEST;
- } else if (manifest.type != s.MANIFEST) {
- var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");
- this._sendError(event);
- }
- fileList = [manifest];
-
- // An object that defines a manifest
- } else if (manifest.manifest !== undefined) {
- fileList = manifest.manifest;
- path = manifest.path;
- }
-
- // Unsupported. This will throw an error.
- } else {
- var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");
- this._sendError(event);
- return;
- }
-
- for (var i = 0, l = fileList.length; i < l; i++) {
- this._addItem(fileList[i], path, basePath);
- }
-
- if (loadNow !== false) {
- this.setPaused(false);
- } else {
- this.setPaused(true);
- }
-
- };
-
- /**
- * Start a LoadQueue that was created, but not automatically started.
- * @method load
- */
- p.load = function () {
- this.setPaused(false);
- };
-
- /**
- * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
- * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
- * `basePath` will not be part of the ID.
- * @method getItem
- * @param {String} value The id
or src
of the load item.
- * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
- * event as the `item` parameter.
- */
- p.getItem = function (value) {
- return this._loadItemsById[value] || this._loadItemsBySrc[value];
- };
-
- /**
- * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
- * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
- * `basePath` will not be part of the ID.
- * @method getResult
- * @param {String} value The id
or src
of the load item.
- * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
- * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
- * returned instead.
- * @return {Object} A result object containing the content that was loaded, such as:
- *
- * - An image tag (<image />) for images
- * - A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML
- * DOM.
- * - A style tag for CSS (<style /> or <link >)
- * - Raw text for TEXT
- * - A formatted JavaScript object defined by JSON
- * - An XML document
- * - A binary arraybuffer loaded by XHR
- * - An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play
- * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
- * which can not be used to play audio back.
- *
- * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
- * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
- */
- p.getResult = function (value, rawResult) {
- var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
- if (item == null) {
- return null;
- }
- var id = item.id;
- if (rawResult && this._loadedRawResults[id]) {
- return this._loadedRawResults[id];
- }
- return this._loadedResults[id];
- };
-
- /**
- * Generate an list of items loaded by this queue.
- * @method getItems
- * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
- * and failed load items will also be included.
- * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
- * result, and rawResult.
- * @since 0.6.0
- */
- p.getItems = function (loaded) {
- var arr = [];
- for (var n in this._loadItemsById) {
- var item = this._loadItemsById[n];
- var result = this.getResult(n);
- if (loaded === true && result == null) {
- continue;
- }
- arr.push({
- item: item,
- result: result,
- rawResult: this.getResult(n, true)
- });
- }
- return arr;
- };
-
- /**
- * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
- * be processed when active loads complete. LoadQueues are not paused by default.
- *
- * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
- * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
- * argument is `false`.
- * @method setPaused
- * @param {Boolean} value Whether the queue should be paused or not.
- */
- p.setPaused = function (value) {
- this._paused = value;
- if (!this._paused) {
- this._loadNext();
- }
- };
-
- /**
- * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
- * starting to download. Note that currently any active loads will remain open, and events may be processed.
- *
- * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
- * @method close
- */
- p.close = function () {
- while (this._currentLoads.length) {
- this._currentLoads.pop().cancel();
- }
- this._scriptOrder.length = 0;
- this._loadedScripts.length = 0;
- this.loadStartWasDispatched = false;
- this._itemCount = 0;
- this._lastProgress = NaN;
- };
-
-// protected methods
- /**
- * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
- * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
- * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
- * method.
- * @method _addItem
- * @param {String|Object} value The item to add to the queue.
- * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
- * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
- * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
- * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
- * version.
- * @private
- */
- p._addItem = function (value, path, basePath) {
- var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
- if (item == null) {
- return;
- } // Sometimes plugins or types should be skipped.
- var loader = this._createLoader(item);
- if (loader != null) {
- if ("plugins" in loader) {
- loader.plugins = this._plugins;
- }
- item._loader = loader;
- this._loadQueue.push(loader);
- this._loadQueueBackup.push(loader);
-
- this._numItems++;
- this._updateProgress();
-
- // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
- if ((this.maintainScriptOrder
- && item.type == createjs.LoadQueue.JAVASCRIPT
- //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
- )
- || item.maintainOrder === true) {
- this._scriptOrder.push(item);
- this._loadedScripts.push(null);
- }
- }
- };
-
- /**
- * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
- * item is determined by browser support, requirements based on the file type, and developer settings. For example,
- * XHR is only used for file types that support it in new browsers.
- *
- * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
- * alter the load item.
- * @method _createLoadItem
- * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
- * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
- * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
- * when it is added.
- * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to
- * the path argument.
- * @return {Object} The loader instance that will be used.
- * @private
- */
- p._createLoadItem = function (value, path, basePath) {
- var item = createjs.LoadItem.create(value);
- if (item == null) {
- return null;
- }
-
- var bp = ""; // Store the generated basePath
- var useBasePath = basePath || this._basePath;
-
- if (item.src instanceof Object) {
- if (!item.type) {
- return null;
- } // the the src is an object, type is required to pass off to plugin
- if (path) {
- bp = path;
- var pathMatch = createjs.RequestUtils.parseURI(path);
- // Also append basePath
- if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
- bp = useBasePath + bp;
- }
- } else if (useBasePath != null) {
- bp = useBasePath;
- }
- } else {
- // Determine Extension, etc.
- var match = createjs.RequestUtils.parseURI(item.src);
- if (match.extension) {
- item.ext = match.extension;
- }
- if (item.type == null) {
- item.type = createjs.RequestUtils.getTypeByExtension(item.ext);
- }
-
- // Inject path & basePath
- var autoId = item.src;
- if (!match.absolute && !match.relative) {
- if (path) {
- bp = path;
- var pathMatch = createjs.RequestUtils.parseURI(path);
- autoId = path + autoId;
- // Also append basePath
- if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
- bp = useBasePath + bp;
- }
- } else if (useBasePath != null) {
- bp = useBasePath;
- }
- }
- item.src = bp + item.src;
- }
- item.path = bp;
-
- // If there's no id, set one now.
- if (item.id === undefined || item.id === null || item.id === "") {
- item.id = autoId;
- }
-
- // Give plugins a chance to modify the loadItem:
- var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
- if (customHandler) {
- // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
- var result = customHandler.callback.call(customHandler.scope, item, this);
-
- // The plugin will handle the load, or has canceled it. Ignore it.
- if (result === false) {
- return null;
-
- // Load as normal:
- } else if (result === true) {
- // Do Nothing
-
- // Result is a loader class:
- } else if (result != null) {
- item._loader = result;
- }
-
- // Update the extension in case the type changed:
- match = createjs.RequestUtils.parseURI(item.src);
- if (match.extension != null) {
- item.ext = match.extension;
- }
- }
-
- // Store the item for lookup. This also helps clean-up later.
- this._loadItemsById[item.id] = item;
- this._loadItemsBySrc[item.src] = item;
-
- if (item.crossOrigin == null) {
- item.crossOrigin = this._crossOrigin;
- }
-
- return item;
- };
-
- /**
- * Create a loader for a load item.
- * @method _createLoader
- * @param {Object} item A formatted load item that can be used to generate a loader.
- * @return {AbstractLoader} A loader that can be used to load content.
- * @private
- */
- p._createLoader = function (item) {
- if (item._loader != null) { // A plugin already specified a loader
- return item._loader;
- }
-
- // Initially, try and use the provided/supported XHR mode:
- var preferXHR = this.preferXHR;
-
- for (var i = 0; i < this._availableLoaders.length; i++) {
- var loader = this._availableLoaders[i];
- if (loader && loader.canLoadItem(item)) {
- return new loader(item, preferXHR);
- }
- }
-
- // TODO: Log error (requires createjs.log)
- return null;
- };
-
- /**
- * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
- * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
- * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
- * using tags, which have to be loaded one at a time to maintain load order.
- * @method _loadNext
- * @private
- */
- p._loadNext = function () {
- if (this._paused) {
- return;
- }
-
- // Only dispatch loadstart event when the first file is loaded.
- if (!this._loadStartWasDispatched) {
- this._sendLoadStart();
- this._loadStartWasDispatched = true;
- }
-
- // The queue has completed.
- if (this._numItems == this._numItemsLoaded) {
- this.loaded = true;
- this._sendComplete();
-
- // Load the next queue, if it has been defined.
- if (this.next && this.next.load) {
- this.next.load();
- }
- } else {
- this.loaded = false;
- }
-
- // Must iterate forwards to load in the right order.
- for (var i = 0; i < this._loadQueue.length; i++) {
- if (this._currentLoads.length >= this._maxConnections) {
- break;
- }
- var loader = this._loadQueue[i];
-
- // Determine if we should be only loading one tag-script at a time:
- // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
- if (!this._canStartLoad(loader)) {
- continue;
- }
- this._loadQueue.splice(i, 1);
- i--;
- this._loadItem(loader);
- }
- };
-
- /**
- * Begin loading an item. Event listeners are not added to the loaders until the load starts.
- * @method _loadItem
- * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
- * @private
- */
- p._loadItem = function (loader) {
- loader.on("fileload", this._handleFileLoad, this);
- loader.on("progress", this._handleProgress, this);
- loader.on("complete", this._handleFileComplete, this);
- loader.on("error", this._handleError, this);
- loader.on("fileerror", this._handleFileError, this);
- this._currentLoads.push(loader);
- this._sendFileStart(loader.getItem());
- loader.load();
- };
-
- /**
- * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
- * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
- * events.
- * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
- * @private
- * @since 0.6.0
- */
- p._handleFileLoad = function (event) {
- event.target = null;
- this.dispatchEvent(event);
- };
-
- /**
- * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
- * loaders like M
- * @param event
- * @private
- */
- p._handleFileError = function (event) {
- var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item);
- this._sendError(newEvent);
- };
-
- /**
- * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
- * is set to `true`.
- * @method _handleError
- * @param {ErrorEvent} event The error event, containing relevant error information.
- * @private
- */
- p._handleError = function (event) {
- var loader = event.target;
- this._numItemsLoaded++;
-
- this._finishOrderedItem(loader, true);
- this._updateProgress();
-
- var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
- // TODO: Propagate actual error message.
-
- this._sendError(newEvent);
-
- if (!this.stopOnError) {
- this._removeLoadItem(loader);
- this._cleanLoadItem(loader);
- this._loadNext();
- } else {
- this.setPaused(true);
- }
- };
-
- /**
- * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
- * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
- * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
- * @method _handleFileComplete
- * @param {Event} event The event object from the loader.
- * @private
- */
- p._handleFileComplete = function (event) {
- var loader = event.target;
- var item = loader.getItem();
-
- var result = loader.getResult();
- this._loadedResults[item.id] = result;
- var rawResult = loader.getResult(true);
- if (rawResult != null && rawResult !== result) {
- this._loadedRawResults[item.id] = rawResult;
- }
-
- this._saveLoadedItems(loader);
-
- // Remove the load item
- this._removeLoadItem(loader);
-
- if (!this._finishOrderedItem(loader)) {
- // The item was NOT managed, so process it now
- this._processFinishedLoad(item, loader);
- }
-
- // Clean up the load item
- this._cleanLoadItem(loader);
- };
-
- /**
- * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
- * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
- * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
- * methods.
- * @method _saveLoadedItems
- * @param {AbstractLoader} loader
- * @protected
- * @since 0.6.0
- */
- p._saveLoadedItems = function (loader) {
- // TODO: Not sure how to handle this. Would be nice to expose the items.
- // Loaders may load sub-items. This adds them to this queue
- var list = loader.getLoadedItems();
- if (list === null) {
- return;
- }
-
- for (var i = 0; i < list.length; i++) {
- var item = list[i].item;
-
- // Store item lookups
- this._loadItemsBySrc[item.src] = item;
- this._loadItemsById[item.id] = item;
-
- // Store loaded content
- this._loadedResults[item.id] = list[i].result;
- this._loadedRawResults[item.id] = list[i].rawResult;
- }
- };
-
- /**
- * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
- * so, trigger prior items to trigger as well.
- * @method _finishOrderedItem
- * @param {AbstractLoader} loader
- * @param {Boolean} loadFailed
- * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
- * behaviour if it is.
- * @private
- */
- p._finishOrderedItem = function (loader, loadFailed) {
- var item = loader.getItem();
-
- if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
- || item.maintainOrder) {
-
- //TODO: Evaluate removal of the _currentlyLoadingScript
- if (loader instanceof createjs.JavaScriptLoader) {
- this._currentlyLoadingScript = false;
- }
-
- var index = createjs.indexOf(this._scriptOrder, item);
- if (index == -1) {
- return false;
- } // This loader no longer exists
- this._loadedScripts[index] = (loadFailed === true) ? true : item;
-
- this._checkScriptLoadOrder();
- return true;
- }
-
- return false;
- };
-
- /**
- * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
- * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
- * and then when they are processed and dispatched, the value is set to `true`. This method simply
- * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
- * dispatched.
- * @method _checkScriptLoadOrder
- * @private
- */
- p._checkScriptLoadOrder = function () {
- var l = this._loadedScripts.length;
-
- for (var i = 0; i < l; i++) {
- var item = this._loadedScripts[i];
- if (item === null) {
- break;
- } // This is still loading. Do not process further.
- if (item === true) {
- continue;
- } // This has completed, and been processed. Move on.
-
- var loadItem = this._loadedResults[item.id];
- if (item.type == createjs.LoadQueue.JAVASCRIPT) {
- // Append script tags to the head automatically.
- createjs.DomUtils.appendToHead(loadItem);
- }
-
- var loader = item._loader;
- this._processFinishedLoad(item, loader);
- this._loadedScripts[i] = true;
- }
- };
-
- /**
- * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
- * the next item.
- * @method _processFinishedLoad
- * @param {LoadItem|Object} item
- * @param {AbstractLoader} loader
- * @protected
- */
- p._processFinishedLoad = function (item, loader) {
- this._numItemsLoaded++;
-
- // Since LoadQueue needs maintain order, we can't append scripts in the loader.
- // So we do it here instead. Or in _checkScriptLoadOrder();
- if (!this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) {
- var tag = loader.getTag();
- createjs.DomUtils.appendToHead(tag);
- }
-
- this._updateProgress();
- this._sendFileComplete(item, loader);
- this._loadNext();
- };
-
- /**
- * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
- * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before
- * the script can even be started, since it exist in the DOM while loading.
- * @method _canStartLoad
- * @param {AbstractLoader} loader The loader for the item
- * @return {Boolean} Whether the item can start a load or not.
- * @private
- */
- p._canStartLoad = function (loader) {
- if (!this.maintainScriptOrder || loader.preferXHR) {
- return true;
- }
- var item = loader.getItem();
- if (item.type != createjs.LoadQueue.JAVASCRIPT) {
- return true;
- }
- if (this._currentlyLoadingScript) {
- return false;
- }
-
- var index = this._scriptOrder.indexOf(item);
- var i = 0;
- while (i < index) {
- var checkItem = this._loadedScripts[i];
- if (checkItem == null) {
- return false;
- }
- i++;
- }
- this._currentlyLoadingScript = true;
- return true;
- };
-
- /**
- * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
- * @method _removeLoadItem
- * @param {AbstractLoader} loader A loader instance to remove.
- * @private
- */
- p._removeLoadItem = function (loader) {
- var l = this._currentLoads.length;
- for (var i = 0; i < l; i++) {
- if (this._currentLoads[i] == loader) {
- this._currentLoads.splice(i, 1);
- break;
- }
- }
- };
-
- /**
- * Remove unneeded references from a loader.
- *
- * @param loader
- * @private
- */
- p._cleanLoadItem = function(loader) {
- var item = loader.getItem();
- if (item) {
- delete item._loader;
- }
- }
-
- /**
- * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
- * @method _handleProgress
- * @param {ProgressEvent} event The progress event from the item.
- * @private
- */
- p._handleProgress = function (event) {
- var loader = event.target;
- this._sendFileProgress(loader.getItem(), loader.progress);
- this._updateProgress();
- };
-
- /**
- * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
- * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
- * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
- * loaded progress on top of the already-loaded items.
- *
- * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
- *
- * - 5/10 of the items in the queue (50%)
- * - plus 20% of item 6's slot (2%)
- * - equals 52%
- *
- * @method _updateProgress
- * @private
- */
- p._updateProgress = function () {
- var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
- var remaining = this._numItems - this._numItemsLoaded;
- if (remaining > 0) {
- var chunk = 0;
- for (var i = 0, l = this._currentLoads.length; i < l; i++) {
- chunk += this._currentLoads[i].progress;
- }
- loaded += (chunk / remaining) * (remaining / this._numItems);
- }
-
- if (this._lastProgress != loaded) {
- this._sendProgress(loaded);
- this._lastProgress = loaded;
- }
- };
-
- /**
- * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
- * hashes.
- * @method _disposeItem
- * @param {LoadItem|Object} item The item that was passed in for preloading.
- * @private
- */
- p._disposeItem = function (item) {
- delete this._loadedResults[item.id];
- delete this._loadedRawResults[item.id];
- delete this._loadItemsById[item.id];
- delete this._loadItemsBySrc[item.src];
- };
-
- /**
- * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
- * event for details on the event payload.
- * @method _sendFileProgress
- * @param {LoadItem|Object} item The item that is being loaded.
- * @param {Number} progress The amount the item has been loaded (between 0 and 1).
- * @protected
- */
- p._sendFileProgress = function (item, progress) {
- if (this._isCanceled() || this._paused) {
- return;
- }
- if (!this.hasEventListener("fileprogress")) {
- return;
- }
-
- //LM: Rework ProgressEvent to support this?
- var event = new createjs.Event("fileprogress");
- event.progress = progress;
- event.loaded = progress;
- event.total = 1;
- event.item = item;
-
- this.dispatchEvent(event);
- };
-
- /**
- * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
- * details on the event payload.
- * @method _sendFileComplete
- * @param {LoadItemObject} item The item that is being loaded.
- * @param {AbstractLoader} loader
- * @protected
- */
- p._sendFileComplete = function (item, loader) {
- if (this._isCanceled() || this._paused) {
- return;
- }
-
- var event = new createjs.Event("fileload");
- event.loader = loader;
- event.item = item;
- event.result = this._loadedResults[item.id];
- event.rawResult = this._loadedRawResults[item.id];
-
- // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
- if (item.completeHandler) {
- item.completeHandler(event);
- }
-
- this.hasEventListener("fileload") && this.dispatchEvent(event);
- };
-
- /**
- * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
- * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
- * @method _sendFileStart
- * @param {LoadItem|Object} item The item that is being loaded.
- * @protected
- */
- p._sendFileStart = function (item) {
- var event = new createjs.Event("filestart");
- event.item = item;
- this.hasEventListener("filestart") && this.dispatchEvent(event);
- };
-
- p.toString = function () {
- return "[PreloadJS LoadQueue]";
- };
-
- createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader");
-}());
-
-//##############################################################################
-// TextLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for Text files.
- * @class TextLoader
- * @param {LoadItem|Object} loadItem
- * @extends AbstractLoader
- * @constructor
- */
- function TextLoader(loadItem) {
- this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.TEXT);
- };
-
- var p = createjs.extend(TextLoader, createjs.AbstractLoader);
- var s = TextLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}},
- * but is also the default loader if a file type can not be determined.
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.TEXT;
- };
-
- createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// BinaryLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer.
- * @class BinaryLoader
- * @param {LoadItem|Object} loadItem
- * @extends AbstractLoader
- * @constructor
- */
- function BinaryLoader(loadItem) {
- this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.BINARY);
- this.on("initialize", this._updateXHR, this);
- };
-
- var p = createjs.extend(BinaryLoader, createjs.AbstractLoader);
- var s = BinaryLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.BINARY;
- };
-
- // private methods
- /**
- * Before the item loads, set the response type to "arraybuffer"
- * @property _updateXHR
- * @param {Event} event
- * @private
- */
- p._updateXHR = function (event) {
- event.loader.setResponseType("arraybuffer");
- };
-
- createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// CSSLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for CSS files.
- * @class CSSLoader
- * @param {LoadItem|Object} loadItem
- * @param {Boolean} preferXHR
- * @extends AbstractLoader
- * @constructor
- */
- function CSSLoader(loadItem, preferXHR) {
- this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.CSS);
-
- // public properties
- this.resultFormatter = this._formatResult;
-
- // protected properties
- this._tagSrcAttribute = "href";
-
- if (preferXHR) {
- this._tag = document.createElement("style");
- } else {
- this._tag = document.createElement("link");
- }
-
- this._tag.rel = "stylesheet";
- this._tag.type = "text/css";
- };
-
- var p = createjs.extend(CSSLoader, createjs.AbstractLoader);
- var s = CSSLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}.
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.CSS;
- };
-
- // protected methods
- /**
- * The result formatter for CSS files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {HTMLLinkElement|HTMLStyleElement}
- * @private
- */
- p._formatResult = function (loader) {
- if (this._preferXHR) {
- var tag = loader.getTag();
-
- if (tag.styleSheet) { // IE
- tag.styleSheet.cssText = loader.getResult(true);
- } else {
- var textNode = document.createTextNode(loader.getResult(true));
- tag.appendChild(textNode);
- }
- } else {
- tag = this._tag;
- }
-
- createjs.DomUtils.appendToHead(tag);
-
- return tag;
- };
-
- createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// ImageLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for image files.
- * @class ImageLoader
- * @param {LoadItem|Object} loadItem
- * @param {Boolean} preferXHR
- * @extends AbstractLoader
- * @constructor
- */
- function ImageLoader (loadItem, preferXHR) {
- this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE);
-
- // public properties
- this.resultFormatter = this._formatResult;
-
- // protected properties
- this._tagSrcAttribute = "src";
-
- // Check if the preload item is already a tag.
- if (createjs.RequestUtils.isImageTag(loadItem)) {
- this._tag = loadItem;
- } else if (createjs.RequestUtils.isImageTag(loadItem.src)) {
- this._tag = loadItem.src;
- } else if (createjs.RequestUtils.isImageTag(loadItem.tag)) {
- this._tag = loadItem.tag;
- }
-
- if (this._tag != null) {
- this._preferXHR = false;
- } else {
- this._tag = document.createElement("img");
- }
-
- this.on("initialize", this._updateXHR, this);
- };
-
- var p = createjs.extend(ImageLoader, createjs.AbstractLoader);
- var s = ImageLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.IMAGE;
- };
-
- // public methods
- p.load = function () {
- if (this._tag.src != "" && this._tag.complete) {
- this._sendComplete();
- return;
- }
-
- var crossOrigin = this._item.crossOrigin;
- if (crossOrigin == true) { crossOrigin = "Anonymous"; }
- if (crossOrigin != null && !createjs.RequestUtils.isLocal(this._item.src)) {
- this._tag.crossOrigin = crossOrigin;
- }
-
- this.AbstractLoader_load();
- };
-
- // protected methods
- /**
- * Before the item loads, set its mimeType and responseType.
- * @property _updateXHR
- * @param {Event} event
- * @private
- */
- p._updateXHR = function (event) {
- event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';
-
- // Only exists for XHR
- if (event.loader.setResponseType) {
- event.loader.setResponseType("blob");
- }
- };
-
- /**
- * The result formatter for Image files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {HTMLImageElement}
- * @private
- */
- p._formatResult = function (loader) {
- return this._formatImage;
- };
-
- /**
- * The asynchronous image formatter function. This is required because images have
- * a short delay before they are ready.
- * @method _formatImage
- * @param {Function} successCallback The method to call when the result has finished formatting
- * @param {Function} errorCallback The method to call if an error occurs during formatting
- * @private
- */
- p._formatImage = function (successCallback, errorCallback) {
- var tag = this._tag;
- var URL = window.URL || window.webkitURL;
-
- if (!this._preferXHR) {
- //document.body.removeChild(tag);
- } else if (URL) {
- var objURL = URL.createObjectURL(this.getResult(true));
- tag.src = objURL;
-
- tag.addEventListener("load", this._cleanUpURL, false);
- tag.addEventListener("error", this._cleanUpURL, false);
- } else {
- tag.src = loader.getItem().src;
- }
-
- if (tag.complete) {
- successCallback(tag);
- } else {
- tag.addEventListener("load", createjs.proxy(function(event) {
- successCallback(this._tag);
- }, this), false);
- tag.addEventListener("error", createjs.proxy(function(event) {
- errorCallback(this._tag);
- }, this), false);
- }
- };
-
- /**
- * Clean up the ObjectURL, the tag is done with it. Note that this function is run
- * as an event listener without a proxy/closure, as it doesn't require it - so do not
- * include any functionality that requires scope without changing it.
- * @method _cleanUpURL
- * @param event
- * @private
- */
- p._cleanUpURL = function (event) {
- var URL = window.URL || window.webkitURL;
- URL.revokeObjectURL(event.target.src);
- };
-
- createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// JavaScriptLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for JavaScript files.
- * @class JavaScriptLoader
- * @param {LoadItem|Object} loadItem
- * @param {Boolean} preferXHR
- * @extends AbstractLoader
- * @constructor
- */
- function JavaScriptLoader(loadItem, preferXHR) {
- this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.JAVASCRIPT);
-
- // public properties
- this.resultFormatter = this._formatResult;
-
- // protected properties
- this._tagSrcAttribute = "src";
- this.setTag(document.createElement("script"));
- };
-
- var p = createjs.extend(JavaScriptLoader, createjs.AbstractLoader);
- var s = JavaScriptLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.JAVASCRIPT;
- };
-
- // protected methods
- /**
- * The result formatter for JavaScript files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {HTMLLinkElement|HTMLStyleElement}
- * @private
- */
- p._formatResult = function (loader) {
- var tag = loader.getTag();
- if (this._preferXHR) {
- tag.text = loader.getResult(true);
- }
- return tag;
- };
-
- createjs.JavaScriptLoader = createjs.promote(JavaScriptLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// JSONLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for JSON files. To load JSON cross-domain, use JSONP and the {{#crossLink "JSONPLoader"}}{{/crossLink}}
- * instead. To load JSON-formatted manifests, use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to
- * load EaselJS SpriteSheets, use {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}.
- * @class JSONLoader
- * @param {LoadItem|Object} loadItem
- * @extends AbstractLoader
- * @constructor
- */
- function JSONLoader(loadItem) {
- this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.JSON);
-
- // public properties
- this.resultFormatter = this._formatResult;
- };
-
- var p = createjs.extend(JSONLoader, createjs.AbstractLoader);
- var s = JSONLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}.
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.JSON;
- };
-
- // protected methods
- /**
- * The result formatter for JSON files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {HTMLLinkElement|HTMLStyleElement}
- * @private
- */
- p._formatResult = function (loader) {
- var json = null;
- try {
- json = createjs.DataUtils.parseJSON(loader.getResult(true));
- } catch (e) {
- var event = new createjs.ErrorEvent("JSON_FORMAT", null, e);
- this._sendError(event);
- return e;
- }
-
- return json;
- };
-
- createjs.JSONLoader = createjs.promote(JSONLoader, "AbstractLoader");
-
-}());
-
-//##############################################################################
-// JSONPLoader.js
-//##############################################################################
-
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for JSONP files, which are JSON-formatted text files, wrapped in a callback. To load regular JSON
- * without a callback use the {{#crossLink "JSONLoader"}}{{/crossLink}} instead. To load JSON-formatted manifests,
- * use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to load EaselJS SpriteSheets, use
- * {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}.
- *
- * Note that JSONP files loaded concurrently require a unique callback. To ensure JSONP files are loaded
- * in order, either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1),
- * or set {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback.
- * @class JSONPLoader
- * @param {LoadItem|Object} loadItem
- * @extends AbstractLoader
- * @constructor
- */
- function JSONPLoader(loadItem) {
- this.AbstractLoader_constructor(loadItem, false, createjs.AbstractLoader.JSONP);
- this.setTag(document.createElement("script"));
- this.getTag().type = "text/javascript";
- };
-
- var p = createjs.extend(JSONPLoader, createjs.AbstractLoader);
- var s = JSONPLoader;
-
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}.
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.JSONP;
- };
-
- // public methods
- p.cancel = function () {
- this.AbstractLoader_cancel();
- this._dispose();
- };
-
- /**
- * Loads the JSONp file. Because of the unique loading needs of JSONp
- * we don't use the AbstractLoader.load() method.
- *
- * @method load
- *
- */
- p.load = function () {
- if (this._item.callback == null) {
- throw new Error('callback is required for loading JSONP requests.');
- }
-
- // TODO: Look into creating our own iFrame to handle the load
- // In the first attempt, FF did not get the result
- // result instanceof Object did not work either
- // so we would need to clone the result.
- if (window[this._item.callback] != null) {
- throw new Error(
- "JSONP callback '" +
- this._item.callback +
- "' already exists on window. You need to specify a different callback or re-name the current one.");
- }
-
- window[this._item.callback] = createjs.proxy(this._handleLoad, this);
- window.document.body.appendChild(this._tag);
-
- this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
-
- // Load the tag
- this._tag.src = this._item.src;
- };
-
- // private methods
- /**
- * Handle the JSONP callback, which is a public method defined on `window`.
- * @method _handleLoad
- * @param {Object} data The formatted JSON data.
- * @private
- */
- p._handleLoad = function (data) {
- this._result = this._rawResult = data;
- this._sendComplete();
-
- this._dispose();
- };
-
- /**
- * The tag request has not loaded within the time specfied in loadTimeout.
- * @method _handleError
- * @param {Object} event The XHR error event.
- * @private
- */
- p._handleTimeout = function () {
- this._dispose();
- this.dispatchEvent(new createjs.ErrorEvent("timeout"));
- };
-
- /**
- * Clean up the JSONP load. This clears out the callback and script tag that this loader creates.
- * @method _dispose
- * @private
- */
- p._dispose = function () {
- window.document.body.removeChild(this._tag);
- delete window[this._item.callback];
-
- clearTimeout(this._loadTimeout);
- };
-
- createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader");
-
-}());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+/*
+ TODO: WINDOWS ISSUES
+ * No error for HTML audio in IE 678
+ * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR
+ * No script complete handler in IE 67 TAGS (XHR is fine)
+ * No XML/JSON in IE6 TAGS
+ * Need to hide loading SVG in Opera TAGS
+ * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking)
+ * SVG no load or failure in Opera XHR
+ * Reported issues with IE7/8
+ */
+
+(function (createjs) {
+ "use strict";
+
+// constructor
+ /**
+ * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either
+ * a single file, or queue of files.
+ *
+ * Creating a Queue
+ * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR
+ * argument to false.
+ *
+ * var queue = new createjs.LoadQueue(true);
+ *
+ * Listening for Events
+ * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}}
+ * lets you add as many listeners as you want for events. You can subscribe to the following events:
+ * - {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all
+ * files
+ * - {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with
+ * any file.
+ * - {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has
+ * changed.
+ * - {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
+ * - {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note
+ * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
+ *
+ *
+ * queue.on("fileload", handleFileLoad, this);
+ * queue.on("complete", handleComplete, this);
+ *
+ * Adding files and manifests
+ * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a
+ * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are
+ * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you
+ * like.
+ *
+ * queue.loadFile("filePath/file.jpg");
+ * queue.loadFile({id:"image", src:"filePath/file.jpg"});
+ * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]);
+ *
+ * // Use an external manifest
+ * queue.loadManifest("path/to/manifest.json");
+ * queue.loadManifest({src:"manifest.json", type:"manifest"});
+ *
+ * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not
+ * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin
+ * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a
+ * `loadNow` argument of `true`.
+ *
+ * queue.load();
+ *
+ * File Types
+ * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS
+ * should handle the majority of standard file and url formats, and works with common file extensions. If you have
+ * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a
+ * type
property with any manifest item.
+ *
+ * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.AbstractLoader.SOUND});
+ *
+ * // Note that PreloadJS will not read a file extension from the query string
+ * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.AbstractLoader.IMAGE});
+ *
+ * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
+ *
+ * - {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
+ * - {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files
+ * - {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats
+ * - {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
+ * - {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data
+ * - {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
+ * - {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see
+ * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
+ * - {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats
+ * - {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This
+ * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
+ * - {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files
+ * - {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only
+ * - {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}: Video objects
+ * - {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data
+ *
+ *
+ * Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better
+ * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but
+ * are deprecated.
+ *
+ * Handling Results
+ * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is
+ * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a
+ * formatted object that can be used immediately, including:
+ *
+ * - Binary: The binary loaded result
+ * - CSS: A <link /> tag
+ * - Image: An <img /> tag
+ * - JavaScript: A <script /> tag
+ * - JSON/JSONP: A formatted JavaScript Object
+ * - Manifest: A JavaScript object.
+ *
- Sound: An <audio /> tag
+ *
- SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images.
+ *
- SVG: An <object /> tag
+ * - Text: Raw text
+ * - Video: A Video DOM node
+ * - XML: An XML DOM node
+ *
+ *
+ * function handleFileLoad(event) {
+ * var item = event.item; // A reference to the item that was passed in to the LoadQueue
+ * var type = item.type;
+ *
+ * // Add any images to the page body.
+ * if (type == createjs.LoadQueue.IMAGE) {
+ * document.body.appendChild(event.result);
+ * }
+ * }
+ *
+ * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up
+ * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the
+ * "src" or file path can be used instead, including the `path` defined by a manifest, but not including
+ * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content.
+ *
+ * var image = queue.getResult("image");
+ * document.body.appendChild(image);
+ *
+ * Raw loaded content can be accessed using the rawResult
property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
+ * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
+ * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
+ *
+ * var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
+ *
+ * Plugins
+ * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio,
+ * make sure to install the SoundJS Sound class, which will help load HTML audio,
+ * Flash audio, and WebAudio files. This should be installed before loading any audio files.
+ *
+ * queue.installPlugin(createjs.Sound);
+ *
+ * Known Browser Issues
+ *
+ * - Browsers without audio support can not load audio files.
+ * - Safari on Mac OS X can only play HTML audio if QuickTime is installed
+ * - HTML Audio tags will only download until their
canPlayThrough
event is fired. Browsers other
+ * than Chrome will continue to download in the background.
+ * - When loading scripts using tags, they are automatically added to the document.
+ * - Scripts loaded via XHR may not be properly inspectable with browser tools.
+ * - IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require
+ * XHR to work.
+ * - Content loaded via tags will not show progress, and will continue to download in the background when
+ * canceled, although no events will be dispatched.
+ *
+ *
+ * @class LoadQueue
+ * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP
+ * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR
+ * when necessary.
+ * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue
+ * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../`
+ * will not receive a base path.
+ * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To
+ * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any
+ * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin
+ * parameter is deprecated. Use LoadItem.crossOrigin instead
+ *
+ * @constructor
+ * @extends AbstractLoader
+ */
+ function LoadQueue (preferXHR, basePath, crossOrigin) {
+ this.AbstractLoader_constructor();
+
+ /**
+ * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}.
+ * @property _plugins
+ * @type {Array}
+ * @private
+ * @since 0.6.1
+ */
+ this._plugins = [];
+
+ /**
+ * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the
+ * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
+ * method for more information.
+ * @property _typeCallbacks
+ * @type {Object}
+ * @private
+ */
+ this._typeCallbacks = {};
+
+ /**
+ * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the
+ * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
+ * method for more information.
+ * @property _extensionCallbacks
+ * @type {null}
+ * @private
+ */
+ this._extensionCallbacks = {};
+
+ /**
+ * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and
+ * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed.
+ * @property next
+ * @type {LoadQueue}
+ * @default null
+ */
+ this.next = null;
+
+ /**
+ * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head
+ * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas
+ * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order
+ * specified.
+ *
+ * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}}
+ * property on the load item, or by ensuring that only one connection can be open at a time using
+ * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property
+ * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the
+ * `maintainScriptOrder` to `false` during a load will not change items already in a queue.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(3); // Set a higher number to load multiple items at once
+ * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order
+ * queue.loadManifest([
+ * "script1.js",
+ * "script2.js",
+ * "image.png", // Load any time
+ * {src: "image2.png", maintainOrder: true} // Will wait for script2.js
+ * "image3.png",
+ * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR)
+ * ]);
+ *
+ * @property maintainScriptOrder
+ * @type {Boolean}
+ * @default true
+ */
+ this.maintainScriptOrder = true;
+
+ /**
+ * Determines if the LoadQueue will stop processing the current queue when an error is encountered.
+ * @property stopOnError
+ * @type {Boolean}
+ * @default false
+ */
+ this.stopOnError = false;
+
+ /**
+ * The number of maximum open connections that a loadQueue tries to maintain. Please see
+ * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information.
+ * @property _maxConnections
+ * @type {Number}
+ * @default 1
+ * @private
+ */
+ this._maxConnections = 1;
+
+ /**
+ * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the
+ * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can
+ * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is
+ * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the
+ * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of
+ * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}.
+ *
+ * Loaders can be removed from PreloadJS by simply not including them.
+ *
+ * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list
+ * so that they are checked first.
+ * @property _availableLoaders
+ * @type {Array}
+ * @private
+ * @since 0.6.0
+ */
+ this._availableLoaders = [
+ createjs.ImageLoader,
+ createjs.JavaScriptLoader,
+ createjs.CSSLoader,
+ createjs.JSONLoader,
+ createjs.JSONPLoader,
+ createjs.SoundLoader,
+ createjs.ManifestLoader,
+ createjs.SpriteSheetLoader,
+ createjs.XMLLoader,
+ createjs.SVGLoader,
+ createjs.BinaryLoader,
+ createjs.VideoLoader,
+ createjs.TextLoader
+ ];
+
+ /**
+ * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}.
+ * @property _defaultLoaderLength
+ * @type {Number}
+ * @private
+ * @since 0.6.0
+ */
+ this._defaultLoaderLength = this._availableLoaders.length;
+
+ this.init(preferXHR, basePath, crossOrigin);
+ }
+
+ var p = createjs.extend(LoadQueue, createjs.AbstractLoader);
+ var s = LoadQueue;
+
+ /**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+ // p.initialize = function() {}; // searchable for devs wondering where it is.
+
+ /**
+ * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue.
+ * @method init
+ * @param preferXHR
+ * @param basePath
+ * @param crossOrigin
+ * @private
+ */
+ p.init = function (preferXHR, basePath, crossOrigin) {
+
+ // public properties
+ /**
+ * @property useXHR
+ * @type {Boolean}
+ * @readonly
+ * @default true
+ * @deprecated Use preferXHR instead.
+ */
+ this.useXHR = true;
+
+ /**
+ * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR
+ * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR,
+ * and plain text can not be loaded with tags, so it will default the the correct type instead of using the
+ * user-defined type.
+ * @type {Boolean}
+ * @default true
+ * @since 0.6.0
+ */
+ this.preferXHR = true; //TODO: Get/Set
+ this._preferXHR = true;
+ this.setPreferXHR(preferXHR);
+
+ // protected properties
+ /**
+ * Whether the queue is currently paused or not.
+ * @property _paused
+ * @type {boolean}
+ * @private
+ */
+ this._paused = false;
+
+ /**
+ * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The
+ * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such
+ * as `http://`, or a relative path such as `../`.
+ * @property _basePath
+ * @type {String}
+ * @private
+ * @since 0.3.1
+ */
+ this._basePath = basePath;
+
+ /**
+ * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded
+ * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by
+ * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues,
+ * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are ""
+ * and "Anonymous".
+ * @property _crossOrigin
+ * @type {String}
+ * @default ""
+ * @private
+ * @since 0.4.1
+ */
+ this._crossOrigin = crossOrigin;
+
+ /**
+ * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first
+ * file is requested.
+ * @property _loadStartWasDispatched
+ * @type {Boolean}
+ * @default false
+ * @private
+ */
+ this._loadStartWasDispatched = false;
+
+ /**
+ * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when
+ * using a script tag to do preloading.
+ * @property _currentlyLoadingScript
+ * @type {Boolean}
+ * @private
+ */
+ this._currentlyLoadingScript = null;
+
+ /**
+ * An array containing the currently downloading files.
+ * @property _currentLoads
+ * @type {Array}
+ * @private
+ */
+ this._currentLoads = [];
+
+ /**
+ * An array containing the queued items that have not yet started downloading.
+ * @property _loadQueue
+ * @type {Array}
+ * @private
+ */
+ this._loadQueue = [];
+
+ /**
+ * An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
+ * @property _loadQueueBackup
+ * @type {Array}
+ * @private
+ */
+ this._loadQueueBackup = [];
+
+ /**
+ * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}}
+ * id.
+ * @property _loadItemsById
+ * @type {Object}
+ * @private
+ */
+ this._loadItemsById = {};
+
+ /**
+ * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * source.
+ * @property _loadItemsBySrc
+ * @type {Object}
+ * @private
+ */
+ this._loadItemsBySrc = {};
+
+ /**
+ * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @property _loadedResults
+ * @type {Object}
+ * @private
+ */
+ this._loadedResults = {};
+
+ /**
+ * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @property _loadedRawResults
+ * @type {Object}
+ * @private
+ */
+ this._loadedRawResults = {};
+
+ /**
+ * The number of items that have been requested. This helps manage an overall progress without knowing how large
+ * the files are before they are downloaded. This does not include items inside of loaders such as the
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _numItems
+ * @type {Number}
+ * @default 0
+ * @private
+ */
+ this._numItems = 0;
+
+ /**
+ * The number of items that have completed loaded. This helps manage an overall progress without knowing how large
+ * the files are before they are downloaded.
+ * @property _numItemsLoaded
+ * @type {Number}
+ * @default 0
+ * @private
+ */
+ this._numItemsLoaded = 0;
+
+ /**
+ * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right
+ * order.
+ * @property _scriptOrder
+ * @type {Array}
+ * @private
+ */
+ this._scriptOrder = [];
+
+ /**
+ * A list of scripts that have been loaded. Items are added to this list as null
when they are
+ * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true
+ * once they are complete and have been dispatched.
+ * @property _loadedScripts
+ * @type {Array}
+ * @private
+ */
+ this._loadedScripts = [];
+
+ /**
+ * The last progress amount. This is used to suppress duplicate progress events.
+ * @property _lastProgress
+ * @type {Number}
+ * @private
+ * @since 0.6.0
+ */
+ this._lastProgress = NaN;
+
+ };
+
+// static properties
+ /**
+ * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event is dispatched if the timeout is reached before any data is received.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000
+ * @static
+ * @since 0.4.1
+ * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
+ */
+ s.loadTimeout = 8000;
+
+ /**
+ * The time in milliseconds to assume a load has failed.
+ * @property LOAD_TIMEOUT
+ * @type {Number}
+ * @default 0
+ * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
+ */
+ s.LOAD_TIMEOUT = 0;
+
+// Preload Types
+ /**
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
+ */
+ s.BINARY = createjs.AbstractLoader.BINARY;
+
+ /**
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+ s.CSS = createjs.AbstractLoader.CSS;
+
+ /**
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+ s.IMAGE = createjs.AbstractLoader.IMAGE;
+
+ /**
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+ s.JAVASCRIPT = createjs.AbstractLoader.JAVASCRIPT;
+
+ /**
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
+ */
+ s.JSON = createjs.AbstractLoader.JSON;
+
+ /**
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
+ */
+ s.JSONP = createjs.AbstractLoader.JSONP;
+
+ /**
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.4.1
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
+ */
+ s.MANIFEST = createjs.AbstractLoader.MANIFEST;
+
+ /**
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+ s.SOUND = createjs.AbstractLoader.SOUND;
+
+ /**
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+ s.VIDEO = createjs.AbstractLoader.VIDEO;
+
+ /**
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
+ */
+ s.SVG = createjs.AbstractLoader.SVG;
+
+ /**
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
+ */
+ s.TEXT = createjs.AbstractLoader.TEXT;
+
+ /**
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
+ */
+ s.XML = createjs.AbstractLoader.XML;
+
+ /**
+ * @property POST
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
+ */
+ s.POST = createjs.AbstractLoader.POST;
+
+ /**
+ * @property GET
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
+ */
+ s.GET = createjs.AbstractLoader.GET;
+
+// events
+ /**
+ * This event is fired when an individual file has loaded, and been processed.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.3.0
+ */
+
+ /**
+ * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
+ * @event fileprogress
+ * @since 0.3.0
+ */
+
+ /**
+ * This event is fired when an individual file starts to load.
+ * @event filestart
+ * @param {Object} The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a property.
+ */
+
+ /**
+ * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from
+ * a LoadQueue instance.
+ * @event initialize
+ * @private
+ */
+
+// public methods
+ /**
+ * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
+ * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
+ * once, and will be prepended to the list of available loaders.
+ * @method registerLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
+ * @since 0.6.0
+ */
+ p.registerLoader = function (loader) {
+ if (!loader || !loader.canLoadItem) {
+ throw new Error("loader is of an incorrect type.");
+ } else if (this._availableLoaders.indexOf(loader) != -1) {
+ throw new Error("loader already exists."); //LM: Maybe just silently fail here
+ }
+
+ this._availableLoaders.unshift(loader);
+ };
+
+ /**
+ * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
+ * unregistered, the default loaders will always be available.
+ * @method unregisterLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
+ */
+ p.unregisterLoader = function (loader) {
+ var idx = this._availableLoaders.indexOf(loader);
+ if (idx != -1 && idx < this._defaultLoaderLength - 1) {
+ this._availableLoaders.splice(idx, 1);
+ }
+ };
+
+ /**
+ * @method setUseXHR
+ * @param {Boolean} value The new useXHR value to set.
+ * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
+ * the provided value argument was true.
+ * @since 0.3.0
+ * @deprecated use the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property, or the
+ * {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} method instead.
+ */
+ p.setUseXHR = function (value) {
+ return this.setPreferXHR(value);
+ };
+
+ /**
+ * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
+ * fail, or be ignored depending on the browser's capabilities and the load type.
+ * @method setPreferXHR
+ * @param {Boolean} value
+ * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
+ * @since 0.6.0
+ */
+ p.setPreferXHR = function (value) {
+ // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
+ //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
+ this.preferXHR = (value != false && window.XMLHttpRequest != null);
+ return this.preferXHR;
+ };
+
+ /**
+ * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
+ * content, and allows the queue to be used again.
+ * @method removeAll
+ * @since 0.3.0
+ */
+ p.removeAll = function () {
+ this.remove();
+ };
+
+ /**
+ * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
+ * This also removes internal references to loaded item(s).
+ *
+ * Example
+ *
+ * queue.loadManifest([
+ * {src:"test.png", id:"png"},
+ * {src:"test.jpg", id:"jpg"},
+ * {src:"test.mp3", id:"mp3"}
+ * ]);
+ * queue.remove("png"); // Single item by ID
+ * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
+ * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
+ *
+ * @method remove
+ * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
+ * items, or multiple items as arguments.
+ * @since 0.3.0
+ */
+ p.remove = function (idsOrUrls) {
+ var args = null;
+
+ if (idsOrUrls && !Array.isArray(idsOrUrls)) {
+ args = [idsOrUrls];
+ } else if (idsOrUrls) {
+ args = idsOrUrls;
+ } else if (arguments.length > 0) {
+ return;
+ }
+
+ var itemsWereRemoved = false;
+
+ // Destroy everything
+ if (!args) {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
+ this.init(this.preferXHR, this._basePath);
+
+ // Remove specific items
+ } else {
+ while (args.length) {
+ var item = args.pop();
+ var r = this.getResult(item);
+
+ //Remove from the main load Queue
+ for (i = this._loadQueue.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueue[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueue.splice(i, 1)[0].cancel();
+ break;
+ }
+ }
+
+ //Remove from the backup queue
+ for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueueBackup[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueueBackup.splice(i, 1)[0].cancel();
+ break;
+ }
+ }
+
+ if (r) {
+ this._disposeItem(this.getItem(item));
+ } else {
+ for (var i = this._currentLoads.length - 1; i >= 0; i--) {
+ var loadItem = this._currentLoads[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._currentLoads.splice(i, 1)[0].cancel();
+ itemsWereRemoved = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // If this was called during a load, try to load the next item.
+ if (itemsWereRemoved) {
+ this._loadNext();
+ }
+ }
+ };
+
+ /**
+ * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
+ * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
+ * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
+ * @method reset
+ * @since 0.3.0
+ */
+ p.reset = function () {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
+
+ //Reset the queue to its start state
+ var a = [];
+ for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
+ a.push(this._loadQueueBackup[i].getItem());
+ }
+
+ this.loadManifest(a, false);
+ };
+
+ /**
+ * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
+ * Currently, only one plugin can exist per type/extension.
+ *
+ * When a plugin is installed, a getPreloadHandlers()
method will be called on it. For more information
+ * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
+ * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
+ *
+ * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
+ * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
+ * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
+ * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
+ * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
+ * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
+ *
+ * @method installPlugin
+ * @param {Function} plugin The plugin class to install.
+ */
+ p.installPlugin = function (plugin) {
+ if (plugin == null) {
+ return;
+ }
+
+ if (plugin.getPreloadHandlers != null) {
+ this._plugins.push(plugin);
+ var map = plugin.getPreloadHandlers();
+ map.scope = plugin;
+
+ if (map.types != null) {
+ for (var i = 0, l = map.types.length; i < l; i++) {
+ this._typeCallbacks[map.types[i]] = map;
+ }
+ }
+
+ if (map.extensions != null) {
+ for (i = 0, l = map.extensions.length; i < l; i++) {
+ this._extensionCallbacks[map.extensions[i]] = map;
+ }
+ }
+ }
+ };
+
+ /**
+ * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
+ * number of open connections, so any additional connections may remain in a pending state until the browser
+ * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
+ * is `true`, only one script is loaded at a time due to browser limitations.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(10); // Allow 10 concurrent loads
+ *
+ * @method setMaxConnections
+ * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
+ * is open at any time.
+ */
+ p.setMaxConnections = function (value) {
+ this._maxConnections = value;
+ if (!this._paused && this._loadQueue.length > 0) {
+ this._loadNext();
+ }
+ };
+
+ /**
+ * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method.
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadFile
+ * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+ p.loadFile = function (file, loadNow, basePath) {
+ if (file == null) {
+ var event = new createjs.ErrorEvent("PRELOAD_NO_FILE");
+ this._sendError(event);
+ return;
+ }
+ this._addItem(file, null, basePath);
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+ };
+
+ /**
+ * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
+ * The files in the manifest are requested in the same order, but may complete in a different order if the max
+ * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
+ * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
+ * default).
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadManifest
+ * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
+ * manifests:
+ *
+ * - A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
+ * which defines the list of files to load, and can optionally contain a "path" property, which will be
+ * prepended to each file in the list.
+ * - An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
+ * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
+ * and can optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An object which contains a "manifest" property, which defines the list of files to load, and can
+ * optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An Array of files to load.
+ *
+ *
+ * Each "file" in a manifest can be either:
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+ p.loadManifest = function (manifest, loadNow, basePath) {
+ var fileList = null;
+ var path = null;
+
+ // Array-based list of items
+ if (Array.isArray(manifest)) {
+ if (manifest.length == 0) {
+ var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");
+ this._sendError(event);
+ return;
+ }
+ fileList = manifest;
+
+ // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
+ } else if (typeof(manifest) === "string") {
+ fileList = [
+ {
+ src: manifest,
+ type: s.MANIFEST
+ }
+ ];
+
+ } else if (typeof(manifest) == "object") {
+
+ // An object that defines a manifest path
+ if (manifest.src !== undefined) {
+ if (manifest.type == null) {
+ manifest.type = s.MANIFEST;
+ } else if (manifest.type != s.MANIFEST) {
+ var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");
+ this._sendError(event);
+ }
+ fileList = [manifest];
+
+ // An object that defines a manifest
+ } else if (manifest.manifest !== undefined) {
+ fileList = manifest.manifest;
+ path = manifest.path;
+ }
+
+ // Unsupported. This will throw an error.
+ } else {
+ var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");
+ this._sendError(event);
+ return;
+ }
+
+ for (var i = 0, l = fileList.length; i < l; i++) {
+ this._addItem(fileList[i], path, basePath);
+ }
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+
+ };
+
+ /**
+ * Start a LoadQueue that was created, but not automatically started.
+ * @method load
+ */
+ p.load = function () {
+ this.setPaused(false);
+ };
+
+ /**
+ * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
+ * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getItem
+ * @param {String} value The id
or src
of the load item.
+ * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event as the `item` parameter.
+ */
+ p.getItem = function (value) {
+ return this._loadItemsById[value] || this._loadItemsBySrc[value];
+ };
+
+ /**
+ * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
+ * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getResult
+ * @param {String} value The id
or src
of the load item.
+ * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML
+ * DOM.
+ * - A style tag for CSS (<style /> or <link >)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - A binary arraybuffer loaded by XHR
+ * - An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play
+ * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
+ * which can not be used to play audio back.
+ *
+ * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
+ * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+ p.getResult = function (value, rawResult) {
+ var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
+ if (item == null) {
+ return null;
+ }
+ var id = item.id;
+ if (rawResult && this._loadedRawResults[id]) {
+ return this._loadedRawResults[id];
+ }
+ return this._loadedResults[id];
+ };
+
+ /**
+ * Generate an list of items loaded by this queue.
+ * @method getItems
+ * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
+ * and failed load items will also be included.
+ * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
+ * result, and rawResult.
+ * @since 0.6.0
+ */
+ p.getItems = function (loaded) {
+ var arr = [];
+ for (var n in this._loadItemsById) {
+ var item = this._loadItemsById[n];
+ var result = this.getResult(n);
+ if (loaded === true && result == null) {
+ continue;
+ }
+ arr.push({
+ item: item,
+ result: result,
+ rawResult: this.getResult(n, true)
+ });
+ }
+ return arr;
+ };
+
+ /**
+ * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
+ * be processed when active loads complete. LoadQueues are not paused by default.
+ *
+ * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
+ * argument is `false`.
+ * @method setPaused
+ * @param {Boolean} value Whether the queue should be paused or not.
+ */
+ p.setPaused = function (value) {
+ this._paused = value;
+ if (!this._paused) {
+ this._loadNext();
+ }
+ };
+
+ /**
+ * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
+ * starting to download. Note that currently any active loads will remain open, and events may be processed.
+ *
+ * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
+ * @method close
+ */
+ p.close = function () {
+ while (this._currentLoads.length) {
+ this._currentLoads.pop().cancel();
+ }
+ this._scriptOrder.length = 0;
+ this._loadedScripts.length = 0;
+ this.loadStartWasDispatched = false;
+ this._itemCount = 0;
+ this._lastProgress = NaN;
+ };
+
+// protected methods
+ /**
+ * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
+ * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
+ * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
+ * method.
+ * @method _addItem
+ * @param {String|Object} value The item to add to the queue.
+ * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
+ * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
+ * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
+ * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
+ * version.
+ * @private
+ */
+ p._addItem = function (value, path, basePath) {
+ var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
+ if (item == null) {
+ return;
+ } // Sometimes plugins or types should be skipped.
+ var loader = this._createLoader(item);
+ if (loader != null) {
+ if ("plugins" in loader) {
+ loader.plugins = this._plugins;
+ }
+ item._loader = loader;
+ this._loadQueue.push(loader);
+ this._loadQueueBackup.push(loader);
+
+ this._numItems++;
+ this._updateProgress();
+
+ // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
+ if ((this.maintainScriptOrder
+ && item.type == createjs.LoadQueue.JAVASCRIPT
+ //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
+ )
+ || item.maintainOrder === true) {
+ this._scriptOrder.push(item);
+ this._loadedScripts.push(null);
+ }
+ }
+ };
+
+ /**
+ * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
+ * item is determined by browser support, requirements based on the file type, and developer settings. For example,
+ * XHR is only used for file types that support it in new browsers.
+ *
+ * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
+ * alter the load item.
+ * @method _createLoadItem
+ * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
+ * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
+ * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
+ * when it is added.
+ * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to
+ * the path argument.
+ * @return {Object} The loader instance that will be used.
+ * @private
+ */
+ p._createLoadItem = function (value, path, basePath) {
+ var item = createjs.LoadItem.create(value);
+ if (item == null) {
+ return null;
+ }
+
+ var bp = ""; // Store the generated basePath
+ var useBasePath = basePath || this._basePath;
+
+ if (item.src instanceof Object) {
+ if (!item.type) {
+ return null;
+ } // the the src is an object, type is required to pass off to plugin
+ if (path) {
+ bp = path;
+ var pathMatch = createjs.RequestUtils.parseURI(path);
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ } else {
+ // Determine Extension, etc.
+ var match = createjs.RequestUtils.parseURI(item.src);
+ if (match.extension) {
+ item.ext = match.extension;
+ }
+ if (item.type == null) {
+ item.type = createjs.RequestUtils.getTypeByExtension(item.ext);
+ }
+
+ // Inject path & basePath
+ var autoId = item.src;
+ if (!match.absolute && !match.relative) {
+ if (path) {
+ bp = path;
+ var pathMatch = createjs.RequestUtils.parseURI(path);
+ autoId = path + autoId;
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ }
+ item.src = bp + item.src;
+ }
+ item.path = bp;
+
+ // If there's no id, set one now.
+ if (item.id === undefined || item.id === null || item.id === "") {
+ item.id = autoId;
+ }
+
+ // Give plugins a chance to modify the loadItem:
+ var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
+ if (customHandler) {
+ // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
+ var result = customHandler.callback.call(customHandler.scope, item, this);
+
+ // The plugin will handle the load, or has canceled it. Ignore it.
+ if (result === false) {
+ return null;
+
+ // Load as normal:
+ } else if (result === true) {
+ // Do Nothing
+
+ // Result is a loader class:
+ } else if (result != null) {
+ item._loader = result;
+ }
+
+ // Update the extension in case the type changed:
+ match = createjs.RequestUtils.parseURI(item.src);
+ if (match.extension != null) {
+ item.ext = match.extension;
+ }
+ }
+
+ // Store the item for lookup. This also helps clean-up later.
+ this._loadItemsById[item.id] = item;
+ this._loadItemsBySrc[item.src] = item;
+
+ if (item.crossOrigin == null) {
+ item.crossOrigin = this._crossOrigin;
+ }
+
+ return item;
+ };
+
+ /**
+ * Create a loader for a load item.
+ * @method _createLoader
+ * @param {Object} item A formatted load item that can be used to generate a loader.
+ * @return {AbstractLoader} A loader that can be used to load content.
+ * @private
+ */
+ p._createLoader = function (item) {
+ if (item._loader != null) { // A plugin already specified a loader
+ return item._loader;
+ }
+
+ // Initially, try and use the provided/supported XHR mode:
+ var preferXHR = this.preferXHR;
+
+ for (var i = 0; i < this._availableLoaders.length; i++) {
+ var loader = this._availableLoaders[i];
+ if (loader && loader.canLoadItem(item)) {
+ return new loader(item, preferXHR);
+ }
+ }
+
+ // TODO: Log error (requires createjs.log)
+ return null;
+ };
+
+ /**
+ * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
+ * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
+ * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
+ * using tags, which have to be loaded one at a time to maintain load order.
+ * @method _loadNext
+ * @private
+ */
+ p._loadNext = function () {
+ if (this._paused) {
+ return;
+ }
+
+ // Only dispatch loadstart event when the first file is loaded.
+ if (!this._loadStartWasDispatched) {
+ this._sendLoadStart();
+ this._loadStartWasDispatched = true;
+ }
+
+ // The queue has completed.
+ if (this._numItems == this._numItemsLoaded) {
+ this.loaded = true;
+ this._sendComplete();
+
+ // Load the next queue, if it has been defined.
+ if (this.next && this.next.load) {
+ this.next.load();
+ }
+ } else {
+ this.loaded = false;
+ }
+
+ // Must iterate forwards to load in the right order.
+ for (var i = 0; i < this._loadQueue.length; i++) {
+ if (this._currentLoads.length >= this._maxConnections) {
+ break;
+ }
+ var loader = this._loadQueue[i];
+
+ // Determine if we should be only loading one tag-script at a time:
+ // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
+ if (!this._canStartLoad(loader)) {
+ continue;
+ }
+ this._loadQueue.splice(i, 1);
+ i--;
+ this._loadItem(loader);
+ }
+ };
+
+ /**
+ * Begin loading an item. Event listeners are not added to the loaders until the load starts.
+ * @method _loadItem
+ * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
+ * @private
+ */
+ p._loadItem = function (loader) {
+ loader.on("fileload", this._handleFileLoad, this);
+ loader.on("progress", this._handleProgress, this);
+ loader.on("complete", this._handleFileComplete, this);
+ loader.on("error", this._handleError, this);
+ loader.on("fileerror", this._handleFileError, this);
+ this._currentLoads.push(loader);
+ this._sendFileStart(loader.getItem());
+ loader.load();
+ };
+
+ /**
+ * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
+ * events.
+ * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
+ * @private
+ * @since 0.6.0
+ */
+ p._handleFileLoad = function (event) {
+ event.target = null;
+ this.dispatchEvent(event);
+ };
+
+ /**
+ * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
+ * loaders like M
+ * @param event
+ * @private
+ */
+ p._handleFileError = function (event) {
+ var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item);
+ this._sendError(newEvent);
+ };
+
+ /**
+ * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
+ * is set to `true`.
+ * @method _handleError
+ * @param {ErrorEvent} event The error event, containing relevant error information.
+ * @private
+ */
+ p._handleError = function (event) {
+ var loader = event.target;
+ this._numItemsLoaded++;
+
+ this._finishOrderedItem(loader, true);
+ this._updateProgress();
+
+ var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
+ // TODO: Propagate actual error message.
+
+ this._sendError(newEvent);
+
+ if (!this.stopOnError) {
+ this._removeLoadItem(loader);
+ this._cleanLoadItem(loader);
+ this._loadNext();
+ } else {
+ this.setPaused(true);
+ }
+ };
+
+ /**
+ * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
+ * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
+ * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
+ * @method _handleFileComplete
+ * @param {Event} event The event object from the loader.
+ * @private
+ */
+ p._handleFileComplete = function (event) {
+ var loader = event.target;
+ var item = loader.getItem();
+
+ var result = loader.getResult();
+ this._loadedResults[item.id] = result;
+ var rawResult = loader.getResult(true);
+ if (rawResult != null && rawResult !== result) {
+ this._loadedRawResults[item.id] = rawResult;
+ }
+
+ this._saveLoadedItems(loader);
+
+ // Remove the load item
+ this._removeLoadItem(loader);
+
+ if (!this._finishOrderedItem(loader)) {
+ // The item was NOT managed, so process it now
+ this._processFinishedLoad(item, loader);
+ }
+
+ // Clean up the load item
+ this._cleanLoadItem(loader);
+ };
+
+ /**
+ * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
+ * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
+ * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
+ * methods.
+ * @method _saveLoadedItems
+ * @param {AbstractLoader} loader
+ * @protected
+ * @since 0.6.0
+ */
+ p._saveLoadedItems = function (loader) {
+ // TODO: Not sure how to handle this. Would be nice to expose the items.
+ // Loaders may load sub-items. This adds them to this queue
+ var list = loader.getLoadedItems();
+ if (list === null) {
+ return;
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i].item;
+
+ // Store item lookups
+ this._loadItemsBySrc[item.src] = item;
+ this._loadItemsById[item.id] = item;
+
+ // Store loaded content
+ this._loadedResults[item.id] = list[i].result;
+ this._loadedRawResults[item.id] = list[i].rawResult;
+ }
+ };
+
+ /**
+ * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
+ * so, trigger prior items to trigger as well.
+ * @method _finishOrderedItem
+ * @param {AbstractLoader} loader
+ * @param {Boolean} loadFailed
+ * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
+ * behaviour if it is.
+ * @private
+ */
+ p._finishOrderedItem = function (loader, loadFailed) {
+ var item = loader.getItem();
+
+ if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
+ || item.maintainOrder) {
+
+ //TODO: Evaluate removal of the _currentlyLoadingScript
+ if (loader instanceof createjs.JavaScriptLoader) {
+ this._currentlyLoadingScript = false;
+ }
+
+ var index = createjs.indexOf(this._scriptOrder, item);
+ if (index == -1) {
+ return false;
+ } // This loader no longer exists
+ this._loadedScripts[index] = (loadFailed === true) ? true : item;
+
+ this._checkScriptLoadOrder();
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
+ * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
+ * and then when they are processed and dispatched, the value is set to `true`. This method simply
+ * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
+ * dispatched.
+ * @method _checkScriptLoadOrder
+ * @private
+ */
+ p._checkScriptLoadOrder = function () {
+ var l = this._loadedScripts.length;
+
+ for (var i = 0; i < l; i++) {
+ var item = this._loadedScripts[i];
+ if (item === null) {
+ break;
+ } // This is still loading. Do not process further.
+ if (item === true) {
+ continue;
+ } // This has completed, and been processed. Move on.
+
+ var loadItem = this._loadedResults[item.id];
+ if (item.type == createjs.LoadQueue.JAVASCRIPT) {
+ // Append script tags to the head automatically.
+ createjs.DomUtils.appendToHead(loadItem);
+ }
+
+ var loader = item._loader;
+ this._processFinishedLoad(item, loader);
+ this._loadedScripts[i] = true;
+ }
+ };
+
+ /**
+ * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
+ * the next item.
+ * @method _processFinishedLoad
+ * @param {LoadItem|Object} item
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+ p._processFinishedLoad = function (item, loader) {
+ this._numItemsLoaded++;
+
+ // Since LoadQueue needs maintain order, we can't append scripts in the loader.
+ // So we do it here instead. Or in _checkScriptLoadOrder();
+ if (!this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) {
+ var tag = loader.getTag();
+ createjs.DomUtils.appendToHead(tag);
+ }
+
+ this._updateProgress();
+ this._sendFileComplete(item, loader);
+ this._loadNext();
+ };
+
+ /**
+ * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
+ * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before
+ * the script can even be started, since it exist in the DOM while loading.
+ * @method _canStartLoad
+ * @param {AbstractLoader} loader The loader for the item
+ * @return {Boolean} Whether the item can start a load or not.
+ * @private
+ */
+ p._canStartLoad = function (loader) {
+ if (!this.maintainScriptOrder || loader.preferXHR) {
+ return true;
+ }
+ var item = loader.getItem();
+ if (item.type != createjs.LoadQueue.JAVASCRIPT) {
+ return true;
+ }
+ if (this._currentlyLoadingScript) {
+ return false;
+ }
+
+ var index = this._scriptOrder.indexOf(item);
+ var i = 0;
+ while (i < index) {
+ var checkItem = this._loadedScripts[i];
+ if (checkItem == null) {
+ return false;
+ }
+ i++;
+ }
+ this._currentlyLoadingScript = true;
+ return true;
+ };
+
+ /**
+ * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
+ * @method _removeLoadItem
+ * @param {AbstractLoader} loader A loader instance to remove.
+ * @private
+ */
+ p._removeLoadItem = function (loader) {
+ var l = this._currentLoads.length;
+ for (var i = 0; i < l; i++) {
+ if (this._currentLoads[i] == loader) {
+ this._currentLoads.splice(i, 1);
+ break;
+ }
+ }
+ };
+
+ /**
+ * Remove unneeded references from a loader.
+ *
+ * @param loader
+ * @private
+ */
+ p._cleanLoadItem = function(loader) {
+ var item = loader.getItem();
+ if (item) {
+ delete item._loader;
+ }
+ }
+
+ /**
+ * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
+ * @method _handleProgress
+ * @param {ProgressEvent} event The progress event from the item.
+ * @private
+ */
+ p._handleProgress = function (event) {
+ var loader = event.target;
+ this._sendFileProgress(loader.getItem(), loader.progress);
+ this._updateProgress();
+ };
+
+ /**
+ * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
+ * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
+ * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
+ * loaded progress on top of the already-loaded items.
+ *
+ * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
+ *
+ * - 5/10 of the items in the queue (50%)
+ * - plus 20% of item 6's slot (2%)
+ * - equals 52%
+ *
+ * @method _updateProgress
+ * @private
+ */
+ p._updateProgress = function () {
+ var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
+ var remaining = this._numItems - this._numItemsLoaded;
+ if (remaining > 0) {
+ var chunk = 0;
+ for (var i = 0, l = this._currentLoads.length; i < l; i++) {
+ chunk += this._currentLoads[i].progress;
+ }
+ loaded += (chunk / remaining) * (remaining / this._numItems);
+ }
+
+ if (this._lastProgress != loaded) {
+ this._sendProgress(loaded);
+ this._lastProgress = loaded;
+ }
+ };
+
+ /**
+ * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
+ * hashes.
+ * @method _disposeItem
+ * @param {LoadItem|Object} item The item that was passed in for preloading.
+ * @private
+ */
+ p._disposeItem = function (item) {
+ delete this._loadedResults[item.id];
+ delete this._loadedRawResults[item.id];
+ delete this._loadItemsById[item.id];
+ delete this._loadItemsBySrc[item.src];
+ };
+
+ /**
+ * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendFileProgress
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @param {Number} progress The amount the item has been loaded (between 0 and 1).
+ * @protected
+ */
+ p._sendFileProgress = function (item, progress) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+ if (!this.hasEventListener("fileprogress")) {
+ return;
+ }
+
+ //LM: Rework ProgressEvent to support this?
+ var event = new createjs.Event("fileprogress");
+ event.progress = progress;
+ event.loaded = progress;
+ event.total = 1;
+ event.item = item;
+
+ this.dispatchEvent(event);
+ };
+
+ /**
+ * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
+ * details on the event payload.
+ * @method _sendFileComplete
+ * @param {LoadItemObject} item The item that is being loaded.
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+ p._sendFileComplete = function (item, loader) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+
+ var event = new createjs.Event("fileload");
+ event.loader = loader;
+ event.item = item;
+ event.result = this._loadedResults[item.id];
+ event.rawResult = this._loadedRawResults[item.id];
+
+ // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
+ if (item.completeHandler) {
+ item.completeHandler(event);
+ }
+
+ this.hasEventListener("fileload") && this.dispatchEvent(event);
+ };
+
+ /**
+ * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
+ * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
+ * @method _sendFileStart
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @protected
+ */
+ p._sendFileStart = function (item) {
+ var event = new createjs.Event("filestart");
+ event.item = item;
+ this.hasEventListener("filestart") && this.dispatchEvent(event);
+ };
+
+ p.toString = function () {
+ return "[PreloadJS LoadQueue]";
+ };
+
+ createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader");
+}(scope.createjs));
//##############################################################################
-// ManifestLoader.js
+// TextLoader.js
//##############################################################################
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests
- * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the
- * {{#crossLink "LoadItem"}}{{/crossLink}}.
- *
- * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This
- * example shows a sample manifest definition, as well as how to to include a sub-manifest.
- *
- * {
- * "path": "assets/",
- * "manifest": [
- * "image.png",
- * {"src": "image2.png", "id":"image2"},
- * {"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"}
- * ]
- * }
- *
- * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}},
- * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly.
- *
- * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are
- * higher priority loaders, so manifests must set the {{#crossLink "LoadItem"}}{{/crossLink}}
- * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}.
- * @class ManifestLoader
- * @param {LoadItem|Object} loadItem
- * @extends AbstractLoader
- * @constructor
- */
- function ManifestLoader(loadItem) {
- this.AbstractLoader_constructor(loadItem, null, createjs.AbstractLoader.MANIFEST);
-
- // Public Properties
- /**
- * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}},
- * used to pass plugins to new LoadQueues that may be created.
- * @property _plugins
- * @type {Array}
- * @private
- * @since 0.6.1
- */
- this.plugins = null;
-
-
- // Protected Properties
- /**
- * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest.
- * @property _manifestQueue
- * @type {LoadQueue}
- * @private
- */
- this._manifestQueue = null;
- };
-
- var p = createjs.extend(ManifestLoader, createjs.AbstractLoader);
- var s = ManifestLoader;
-
- // static properties
- /**
- * The amount of progress that the manifest itself takes up.
- * @property MANIFEST_PROGRESS
- * @type {number}
- * @default 0.25 (25%)
- * @private
- * @static
- */
- s.MANIFEST_PROGRESS = 0.25;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.MANIFEST;
- };
-
- // public methods
- p.load = function () {
- this.AbstractLoader_load();
- };
-
- // protected methods
- p._createRequest = function() {
- var callback = this._item.callback;
- if (callback != null) {
- this._request = new createjs.JSONPLoader(this._item);
- } else {
- this._request = new createjs.JSONLoader(this._item);
- }
- };
-
- p.handleEvent = function (event) {
- switch (event.type) {
- case "complete":
- this._rawResult = event.target.getResult(true);
- this._result = event.target.getResult();
- this._sendProgress(s.MANIFEST_PROGRESS);
- this._loadManifest(this._result);
- return;
- case "progress":
- event.loaded *= s.MANIFEST_PROGRESS;
- this.progress = event.loaded / event.total;
- if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
- this._sendProgress(event);
- return;
- }
- this.AbstractLoader_handleEvent(event);
- };
-
- p.destroy = function() {
- this.AbstractLoader_destroy();
- this._manifestQueue.close();
- };
-
- /**
- * Create and load the manifest items once the actual manifest has been loaded.
- * @method _loadManifest
- * @param {Object} json
- * @private
- */
- p._loadManifest = function (json) {
- if (json && json.manifest) {
- var queue = this._manifestQueue = new createjs.LoadQueue();
- queue.on("fileload", this._handleManifestFileLoad, this);
- queue.on("progress", this._handleManifestProgress, this);
- queue.on("complete", this._handleManifestComplete, this, true);
- queue.on("error", this._handleManifestError, this, true);
- for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins
- queue.installPlugin(this.plugins[i]);
- }
- queue.loadManifest(json);
- } else {
- this._sendComplete();
- }
- };
-
- /**
- * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed.
- * @method _handleManifestFileLoad
- * @param {Event} event
- * @private
- */
- p._handleManifestFileLoad = function (event) {
- event.target = null;
- this.dispatchEvent(event);
- };
-
- /**
- * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
- * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader.
- * @method _handleManifestComplete
- * @param {Event} event
- * @private
- */
- p._handleManifestComplete = function (event) {
- this._loadedItems = this._manifestQueue.getItems(true);
- this._sendComplete();
- };
-
- /**
- * The manifest has reported progress.
- * @method _handleManifestProgress
- * @param {ProgressEvent} event
- * @private
- */
- p._handleManifestProgress = function (event) {
- this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS;
- this._sendProgress(this.progress);
- };
-
- /**
- * The manifest has reported an error with one of the files.
- * @method _handleManifestError
- * @param {ErrorEvent} event
- * @private
- */
- p._handleManifestError = function (event) {
- var newEvent = new createjs.Event("fileerror");
- newEvent.item = event.data;
- this.dispatchEvent(newEvent);
- };
-
- createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader");
-
-}());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for Text files.
+ * @class TextLoader
+ * @param {LoadItem|Object} loadItem
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function TextLoader(loadItem) {
+ this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.TEXT);
+ };
+
+ var p = createjs.extend(TextLoader, createjs.AbstractLoader);
+ var s = TextLoader;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}},
+ * but is also the default loader if a file type can not be determined.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.TEXT;
+ };
+
+ createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader");
+
+}(scope.createjs));
//##############################################################################
-// SoundLoader.js
+// BinaryLoader.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
/**
- * A loader for HTML audio files. PreloadJS can not load WebAudio files, as a WebAudio context is required, which
- * should be created by either a library playing the sound (such as SoundJS, or an
- * external framework that handles audio playback. To load content that can be played by WebAudio, use the
- * {{#crossLink "BinaryLoader"}}{{/crossLink}}, and handle the audio context decoding manually.
- * @class SoundLoader
+ * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer.
+ * @class BinaryLoader
* @param {LoadItem|Object} loadItem
- * @param {Boolean} preferXHR
- * @extends AbstractMediaLoader
+ * @extends AbstractLoader
* @constructor
*/
- function SoundLoader(loadItem, preferXHR) {
- this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SOUND);
-
- // protected properties
- if (createjs.RequestUtils.isAudioTag(loadItem)) {
- this._tag = loadItem;
- } else if (createjs.RequestUtils.isAudioTag(loadItem.src)) {
- this._tag = loadItem;
- } else if (createjs.RequestUtils.isAudioTag(loadItem.tag)) {
- this._tag = createjs.RequestUtils.isAudioTag(loadItem) ? loadItem : loadItem.src;
- }
-
- if (this._tag != null) {
- this._preferXHR = false;
- }
+ function BinaryLoader(loadItem) {
+ this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.BINARY);
+ this.on("initialize", this._updateXHR, this);
};
- var p = createjs.extend(SoundLoader, createjs.AbstractMediaLoader);
- var s = SoundLoader;
+ var p = createjs.extend(BinaryLoader, createjs.AbstractLoader);
+ var s = BinaryLoader;
// static methods
/**
* Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}.
+ * {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}
* @method canLoadItem
* @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
* @returns {Boolean} Whether the loader can load the item.
* @static
*/
s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.SOUND;
+ return item.type == createjs.AbstractLoader.BINARY;
};
- // protected methods
- p._createTag = function (src) {
- var tag = document.createElement("audio");
- tag.autoplay = false;
- tag.preload = "none";
-
- //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works.
- tag.src = src;
- return tag;
+ // private methods
+ /**
+ * Before the item loads, set the response type to "arraybuffer"
+ * @property _updateXHR
+ * @param {Event} event
+ * @private
+ */
+ p._updateXHR = function (event) {
+ event.loader.setResponseType("arraybuffer");
};
- createjs.SoundLoader = createjs.promote(SoundLoader, "AbstractMediaLoader");
+ createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader");
-}());
+}(scope.createjs));
//##############################################################################
-// VideoLoader.js
+// CSSLoader.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for CSS files.
+ * @class CSSLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function CSSLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.CSS);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "href";
+
+ if (preferXHR) {
+ this._tag = document.createElement("style");
+ } else {
+ this._tag = document.createElement("link");
+ }
+
+ this._tag.rel = "stylesheet";
+ this._tag.type = "text/css";
+ };
+
+ var p = createjs.extend(CSSLoader, createjs.AbstractLoader);
+ var s = CSSLoader;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.CSS;
+ };
+
+ // protected methods
+ /**
+ * The result formatter for CSS files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLLinkElement|HTMLStyleElement}
+ * @private
+ */
+ p._formatResult = function (loader) {
+ if (this._preferXHR) {
+ var tag = loader.getTag();
+
+ if (tag.styleSheet) { // IE
+ tag.styleSheet.cssText = loader.getResult(true);
+ } else {
+ var textNode = document.createTextNode(loader.getResult(true));
+ tag.appendChild(textNode);
+ }
+ } else {
+ tag = this._tag;
+ }
+
+ createjs.DomUtils.appendToHead(tag);
+
+ return tag;
+ };
+
+ createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader");
+
+}(scope.createjs));
+
+//##############################################################################
+// ImageLoader.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for image files.
+ * @class ImageLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function ImageLoader (loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "src";
+
+ // Check if the preload item is already a tag.
+ if (createjs.RequestUtils.isImageTag(loadItem)) {
+ this._tag = loadItem;
+ } else if (createjs.RequestUtils.isImageTag(loadItem.src)) {
+ this._tag = loadItem.src;
+ } else if (createjs.RequestUtils.isImageTag(loadItem.tag)) {
+ this._tag = loadItem.tag;
+ }
+
+ if (this._tag != null) {
+ this._preferXHR = false;
+ } else {
+ this._tag = document.createElement("img");
+ }
+
+ this.on("initialize", this._updateXHR, this);
+ };
+
+ var p = createjs.extend(ImageLoader, createjs.AbstractLoader);
+ var s = ImageLoader;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.IMAGE;
+ };
+
+ // public methods
+ p.load = function () {
+ if (this._tag.src != "" && this._tag.complete) {
+ this._sendComplete();
+ return;
+ }
+
+ var crossOrigin = this._item.crossOrigin;
+ if (crossOrigin == true) { crossOrigin = "Anonymous"; }
+ if (crossOrigin != null && !createjs.RequestUtils.isLocal(this._item.src)) {
+ this._tag.crossOrigin = crossOrigin;
+ }
+
+ this.AbstractLoader_load();
+ };
+
+ // protected methods
+ /**
+ * Before the item loads, set its mimeType and responseType.
+ * @property _updateXHR
+ * @param {Event} event
+ * @private
+ */
+ p._updateXHR = function (event) {
+ event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';
+
+ // Only exists for XHR
+ if (event.loader.setResponseType) {
+ event.loader.setResponseType("blob");
+ }
+ };
+
+ /**
+ * The result formatter for Image files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLImageElement}
+ * @private
+ */
+ p._formatResult = function (loader) {
+ return this._formatImage;
+ };
+
+ /**
+ * The asynchronous image formatter function. This is required because images have
+ * a short delay before they are ready.
+ * @method _formatImage
+ * @param {Function} successCallback The method to call when the result has finished formatting
+ * @param {Function} errorCallback The method to call if an error occurs during formatting
+ * @private
+ */
+ p._formatImage = function (successCallback, errorCallback) {
+ var tag = this._tag;
+ var URL = window.URL || window.webkitURL;
+
+ if (!this._preferXHR) {
+ //document.body.removeChild(tag);
+ } else if (URL) {
+ var objURL = URL.createObjectURL(this.getResult(true));
+ tag.src = objURL;
+
+ tag.addEventListener("load", this._cleanUpURL, false);
+ tag.addEventListener("error", this._cleanUpURL, false);
+ } else {
+ tag.src = this._item.src;
+ }
+
+ if (tag.complete) {
+ successCallback(tag);
+ } else {
+ tag.onload = createjs.proxy(function() {
+ successCallback(this._tag);
+ }, this);
+
+ tag.onerror = createjs.proxy(function() {
+ errorCallback(_this._tag);
+ }, this);
+ }
+ };
+
+ /**
+ * Clean up the ObjectURL, the tag is done with it. Note that this function is run
+ * as an event listener without a proxy/closure, as it doesn't require it - so do not
+ * include any functionality that requires scope without changing it.
+ * @method _cleanUpURL
+ * @param event
+ * @private
+ */
+ p._cleanUpURL = function (event) {
+ var URL = window.URL || window.webkitURL;
+ URL.revokeObjectURL(event.target.src);
+ };
+
+ createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader");
+
+}(scope.createjs));
+
+//##############################################################################
+// JavaScriptLoader.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
/**
- * A loader for video files.
- * @class VideoLoader
+ * A loader for JavaScript files.
+ * @class JavaScriptLoader
* @param {LoadItem|Object} loadItem
* @param {Boolean} preferXHR
- * @extends AbstractMediaLoader
+ * @extends AbstractLoader
* @constructor
*/
- function VideoLoader(loadItem, preferXHR) {
- this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.VIDEO);
+ function JavaScriptLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.JAVASCRIPT);
- if (createjs.RequestUtils.isVideoTag(loadItem) || createjs.RequestUtils.isVideoTag(loadItem.src)) {
- this.setTag(createjs.RequestUtils.isVideoTag(loadItem)?loadItem:loadItem.src);
+ // public properties
+ this.resultFormatter = this._formatResult;
- // We can't use XHR for a tag that's passed in.
- this._preferXHR = false;
- } else {
- this.setTag(this._createTag());
- }
+ // protected properties
+ this._tagSrcAttribute = "src";
+ this.setTag(document.createElement("script"));
};
- var p = createjs.extend(VideoLoader, createjs.AbstractMediaLoader);
- var s = VideoLoader;
-
- /**
- * Create a new video tag
- *
- * @returns {HTMLElement}
- * @private
- */
- p._createTag = function () {
- return document.createElement("video");
- };
+ var p = createjs.extend(JavaScriptLoader, createjs.AbstractLoader);
+ var s = JavaScriptLoader;
// static methods
/**
* Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}.
+ * {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}
* @method canLoadItem
* @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
* @returns {Boolean} Whether the loader can load the item.
* @static
*/
s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.VIDEO;
+ return item.type == createjs.AbstractLoader.JAVASCRIPT;
};
- createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader");
+ // protected methods
+ /**
+ * The result formatter for JavaScript files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLLinkElement|HTMLStyleElement}
+ * @private
+ */
+ p._formatResult = function (loader) {
+ var tag = loader.getTag();
+ if (this._preferXHR) {
+ tag.text = loader.getResult(true);
+ }
+ return tag;
+ };
+
+ createjs.JavaScriptLoader = createjs.promote(JavaScriptLoader, "AbstractLoader");
+
+}(scope.createjs));
+
+//##############################################################################
+// JSONLoader.js
+//##############################################################################
-}());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for JSON files. To load JSON cross-domain, use JSONP and the {{#crossLink "JSONPLoader"}}{{/crossLink}}
+ * instead. To load JSON-formatted manifests, use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to
+ * load EaselJS SpriteSheets, use {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}.
+ * @class JSONLoader
+ * @param {LoadItem|Object} loadItem
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function JSONLoader(loadItem) {
+ this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.JSON);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+ };
+
+ var p = createjs.extend(JSONLoader, createjs.AbstractLoader);
+ var s = JSONLoader;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.JSON;
+ };
+
+ // protected methods
+ /**
+ * The result formatter for JSON files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLLinkElement|HTMLStyleElement}
+ * @private
+ */
+ p._formatResult = function (loader) {
+ var json = null;
+ try {
+ json = createjs.DataUtils.parseJSON(loader.getResult(true));
+ } catch (e) {
+ var event = new createjs.ErrorEvent("JSON_FORMAT", null, e);
+ this._sendError(event);
+ return e;
+ }
+
+ return json;
+ };
+
+ createjs.JSONLoader = createjs.promote(JSONLoader, "AbstractLoader");
+
+}(scope.createjs));
+
+//##############################################################################
+// JSONPLoader.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for JSONP files, which are JSON-formatted text files, wrapped in a callback. To load regular JSON
+ * without a callback use the {{#crossLink "JSONLoader"}}{{/crossLink}} instead. To load JSON-formatted manifests,
+ * use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to load EaselJS SpriteSheets, use
+ * {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}.
+ *
+ * JSONP is a format that provides a solution for loading JSON files cross-domain without requiring CORS.
+ * JSONP files are loaded as JavaScript, and the "callback" is executed once they are loaded. The callback in the
+ * JSONP must match the callback passed to the loadItem.
+ *
+ * Example JSONP
+ *
+ * callbackName({
+ * "name": "value",
+ * "num": 3,
+ * "obj": { "bool":true }
+ * });
+ *
+ * Example
+ *
+ * var loadItem = {id:"json", type:"jsonp", src:"http://server.com/text.json", callback:"callbackName"}
+ * var queue = new createjs.LoadQueue();
+ * queue.on("complete", handleComplete);
+ * queue.loadItem(loadItem);
+ *
+ * function handleComplete(event) }
+ * var json = queue.getResult("json");
+ * console.log(json.obj.bool); // true
+ * }
+ *
+ * Note that JSONP files loaded concurrently require a unique callback. To ensure JSONP files are loaded
+ * in order, either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1),
+ * or set {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback.
+ *
+ * @class JSONPLoader
+ * @param {LoadItem|Object} loadItem
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function JSONPLoader(loadItem) {
+ this.AbstractLoader_constructor(loadItem, false, createjs.AbstractLoader.JSONP);
+ this.setTag(document.createElement("script"));
+ this.getTag().type = "text/javascript";
+ };
+
+ var p = createjs.extend(JSONPLoader, createjs.AbstractLoader);
+ var s = JSONPLoader;
+
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.JSONP;
+ };
+
+ // public methods
+ p.cancel = function () {
+ this.AbstractLoader_cancel();
+ this._dispose();
+ };
+
+ /**
+ * Loads the JSONp file. Because of the unique loading needs of JSONp
+ * we don't use the AbstractLoader.load() method.
+ *
+ * @method load
+ *
+ */
+ p.load = function () {
+ if (this._item.callback == null) {
+ throw new Error('callback is required for loading JSONP requests.');
+ }
+
+ // TODO: Look into creating our own iFrame to handle the load
+ // In the first attempt, FF did not get the result
+ // result instanceof Object did not work either
+ // so we would need to clone the result.
+ if (window[this._item.callback] != null) {
+ throw new Error(
+ "JSONP callback '" +
+ this._item.callback +
+ "' already exists on window. You need to specify a different callback or re-name the current one.");
+ }
+
+ window[this._item.callback] = createjs.proxy(this._handleLoad, this);
+ window.document.body.appendChild(this._tag);
+
+ this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
+
+ // Load the tag
+ this._tag.src = this._item.src;
+ };
+
+ // private methods
+ /**
+ * Handle the JSONP callback, which is a public method defined on `window`.
+ * @method _handleLoad
+ * @param {Object} data The formatted JSON data.
+ * @private
+ */
+ p._handleLoad = function (data) {
+ this._result = this._rawResult = data;
+ this._sendComplete();
+
+ this._dispose();
+ };
+
+ /**
+ * The tag request has not loaded within the time specfied in loadTimeout.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+ p._handleTimeout = function () {
+ this._dispose();
+ this.dispatchEvent(new createjs.ErrorEvent("timeout"));
+ };
+
+ /**
+ * Clean up the JSONP load. This clears out the callback and script tag that this loader creates.
+ * @method _dispose
+ * @private
+ */
+ p._dispose = function () {
+ window.document.body.removeChild(this._tag);
+ delete window[this._item.callback];
+
+ clearTimeout(this._loadTimeout);
+ };
+
+ createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader");
+
+}(scope.createjs));
//##############################################################################
-// SpriteSheetLoader.js
+// ManifestLoader.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
/**
- * A loader for EaselJS SpriteSheets. Images inside the spritesheet definition are loaded before the loader
- * completes. To load SpriteSheets using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}}
- * as part of the {{#crossLink "LoadItem"}}{{/crossLink}}. Note that the {{#crossLink "JSONLoader"}}{{/crossLink}}
- * and {{#crossLink "JSONPLoader"}}{{/crossLink}} are higher priority loaders, so SpriteSheets must
- * set the {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property
- * to {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}.
+ * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests
+ * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the
+ * {{#crossLink "LoadItem"}}{{/crossLink}}.
+ *
+ * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This
+ * example shows a sample manifest definition, as well as how to to include a sub-manifest.
+ *
+ * {
+ * "path": "assets/",
+ * "manifest": [
+ * "image.png",
+ * {"src": "image2.png", "id":"image2"},
+ * {"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"}
+ * ]
+ * }
*
- * The {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/crossOrigin:property"}}{{/crossLink}} as well
- * as the {{#crossLink "LoadQueue's"}}{{/crossLink}} `basePath` argument and {{#crossLink "LoadQueue/_preferXHR"}}{{/crossLink}}
- * property supplied to the {{#crossLink "LoadQueue"}}{{/crossLink}} are passed on to the sub-manifest that loads
- * the SpriteSheet images.
+ * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}},
+ * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly.
*
- * Note that the SpriteSheet JSON does not respect the {{#crossLink "LoadQueue/_preferXHR:property"}}{{/crossLink}}
- * property, which should instead be determined by the presence of a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}}
- * property on the SpriteSheet load item. This is because the JSON loaded will have a different format depending on
- * if it is loaded as JSON, so just changing `preferXHR` is not enough to change how it is loaded.
- * @class SpriteSheetLoader
+ * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are
+ * higher priority loaders, so manifests must set the {{#crossLink "LoadItem"}}{{/crossLink}}
+ * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}.
+ * @class ManifestLoader
* @param {LoadItem|Object} loadItem
* @extends AbstractLoader
* @constructor
*/
- function SpriteSheetLoader(loadItem, preferXHR) {
- this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SPRITESHEET);
+ function ManifestLoader(loadItem) {
+ this.AbstractLoader_constructor(loadItem, null, createjs.AbstractLoader.MANIFEST);
- // protected properties
+ // Public Properties
+ /**
+ * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}},
+ * used to pass plugins to new LoadQueues that may be created.
+ * @property _plugins
+ * @type {Array}
+ * @private
+ * @since 0.6.1
+ */
+ this.plugins = null;
+
+
+ // Protected Properties
/**
- * An internal queue which loads the SpriteSheet's images.
- * @method _manifestQueue
+ * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest.
+ * @property _manifestQueue
* @type {LoadQueue}
* @private
*/
this._manifestQueue = null;
- }
+ };
- var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader);
- var s = SpriteSheetLoader;
+ var p = createjs.extend(ManifestLoader, createjs.AbstractLoader);
+ var s = ManifestLoader;
// static properties
/**
* The amount of progress that the manifest itself takes up.
- * @property SPRITESHEET_PROGRESS
+ * @property MANIFEST_PROGRESS
* @type {number}
* @default 0.25 (25%)
* @private
* @static
*/
- s.SPRITESHEET_PROGRESS = 0.25;
+ s.MANIFEST_PROGRESS = 0.25;
// static methods
/**
* Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}
+ * {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}
* @method canLoadItem
* @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
* @returns {Boolean} Whether the loader can load the item.
* @static
*/
s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.SPRITESHEET;
+ return item.type == createjs.AbstractLoader.MANIFEST;
};
// public methods
- p.destroy = function() {
- this.AbstractLoader_destroy;
- this._manifestQueue.close();
+ p.load = function () {
+ this.AbstractLoader_load();
};
// protected methods
@@ -7034,11 +6779,11 @@ this.createjs = this.createjs || {};
case "complete":
this._rawResult = event.target.getResult(true);
this._result = event.target.getResult();
- this._sendProgress(s.SPRITESHEET_PROGRESS);
+ this._sendProgress(s.MANIFEST_PROGRESS);
this._loadManifest(this._result);
return;
case "progress":
- event.loaded *= s.SPRITESHEET_PROGRESS;
+ event.loaded *= s.MANIFEST_PROGRESS;
this.progress = event.loaded / event.total;
if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
this._sendProgress(event);
@@ -7047,20 +6792,30 @@ this.createjs = this.createjs || {};
this.AbstractLoader_handleEvent(event);
};
+ p.destroy = function() {
+ this.AbstractLoader_destroy();
+ this._manifestQueue.close();
+ };
+
/**
- * Create and load the images once the SpriteSheet JSON has been loaded.
+ * Create and load the manifest items once the actual manifest has been loaded.
* @method _loadManifest
* @param {Object} json
* @private
*/
p._loadManifest = function (json) {
- if (json && json.images) {
- var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR, this._item.path, this._item.crossOrigin);
- queue.on("complete", this._handleManifestComplete, this, true);
+ if (json && json.manifest) {
+ var queue = this._manifestQueue = new createjs.LoadQueue();
queue.on("fileload", this._handleManifestFileLoad, this);
queue.on("progress", this._handleManifestProgress, this);
+ queue.on("complete", this._handleManifestComplete, this, true);
queue.on("error", this._handleManifestError, this, true);
- queue.loadManifest(json.images);
+ for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins
+ queue.installPlugin(this.plugins[i]);
+ }
+ queue.loadManifest(json);
+ } else {
+ this._sendComplete();
}
};
@@ -7071,40 +6826,35 @@ this.createjs = this.createjs || {};
* @private
*/
p._handleManifestFileLoad = function (event) {
- var image = event.result;
- if (image != null) {
- var images = this.getResult().images;
- var pos = images.indexOf(event.item.src);
- images[pos] = image;
- }
+ event.target = null;
+ this.dispatchEvent(event);
};
/**
- * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
- * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader.
+ * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
+ * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader.
* @method _handleManifestComplete
* @param {Event} event
* @private
*/
p._handleManifestComplete = function (event) {
- this._result = new createjs.SpriteSheet(this._result);
this._loadedItems = this._manifestQueue.getItems(true);
this._sendComplete();
};
/**
- * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress.
+ * The manifest has reported progress.
* @method _handleManifestProgress
* @param {ProgressEvent} event
* @private
*/
p._handleManifestProgress = function (event) {
- this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS;
+ this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS;
this._sendProgress(this.progress);
};
/**
- * An image has reported an error.
+ * The manifest has reported an error with one of the files.
* @method _handleManifestError
* @param {ErrorEvent} event
* @private
@@ -7115,98 +6865,411 @@ this.createjs = this.createjs || {};
this.dispatchEvent(newEvent);
};
- createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader");
+ createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader");
-}());
+}(scope.createjs));
//##############################################################################
-// SVGLoader.js
+// SoundLoader.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for HTML audio files. PreloadJS can not load WebAudio files, as a WebAudio context is required, which
+ * should be created by either a library playing the sound (such as SoundJS, or an
+ * external framework that handles audio playback. To load content that can be played by WebAudio, use the
+ * {{#crossLink "BinaryLoader"}}{{/crossLink}}, and handle the audio context decoding manually.
+ * @class SoundLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractMediaLoader
+ * @constructor
+ */
+ function SoundLoader(loadItem, preferXHR) {
+ this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SOUND);
+
+ // protected properties
+ if (createjs.RequestUtils.isAudioTag(loadItem)) {
+ this._tag = loadItem;
+ } else if (createjs.RequestUtils.isAudioTag(loadItem.src)) {
+ this._tag = loadItem;
+ } else if (createjs.RequestUtils.isAudioTag(loadItem.tag)) {
+ this._tag = createjs.RequestUtils.isAudioTag(loadItem) ? loadItem : loadItem.src;
+ }
+
+ if (this._tag != null) {
+ this._preferXHR = false;
+ }
+ };
+
+ var p = createjs.extend(SoundLoader, createjs.AbstractMediaLoader);
+ var s = SoundLoader;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.SOUND;
+ };
+
+ // protected methods
+ p._createTag = function (src) {
+ var tag = document.createElement("audio");
+ tag.autoplay = false;
+ tag.preload = "none";
+
+ //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works.
+ tag.src = src;
+ return tag;
+ };
+
+ createjs.SoundLoader = createjs.promote(SoundLoader, "AbstractMediaLoader");
+
+}(scope.createjs));
+
+//##############################################################################
+// VideoLoader.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
/**
- * A loader for SVG files.
- * @class SVGLoader
+ * A loader for video files.
+ * @class VideoLoader
* @param {LoadItem|Object} loadItem
* @param {Boolean} preferXHR
- * @extends AbstractLoader
+ * @extends AbstractMediaLoader
* @constructor
*/
- function SVGLoader(loadItem, preferXHR) {
- this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SVG);
-
- // public properties
- this.resultFormatter = this._formatResult;
+ function VideoLoader(loadItem, preferXHR) {
+ this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.VIDEO);
- // protected properties
- this._tagSrcAttribute = "data";
+ if (createjs.RequestUtils.isVideoTag(loadItem) || createjs.RequestUtils.isVideoTag(loadItem.src)) {
+ this.setTag(createjs.RequestUtils.isVideoTag(loadItem)?loadItem:loadItem.src);
- if (preferXHR) {
- this.setTag(document.createElement("svg"));
+ // We can't use XHR for a tag that's passed in.
+ this._preferXHR = false;
} else {
- this.setTag(document.createElement("object"));
- this.getTag().type = "image/svg+xml";
+ this.setTag(this._createTag());
}
};
- var p = createjs.extend(SVGLoader, createjs.AbstractLoader);
- var s = SVGLoader;
+ var p = createjs.extend(VideoLoader, createjs.AbstractMediaLoader);
+ var s = VideoLoader;
+
+ /**
+ * Create a new video tag
+ *
+ * @returns {HTMLElement}
+ * @private
+ */
+ p._createTag = function () {
+ return document.createElement("video");
+ };
// static methods
/**
* Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}
+ * {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}.
* @method canLoadItem
* @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
* @returns {Boolean} Whether the loader can load the item.
* @static
*/
s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.SVG;
+ return item.type == createjs.AbstractLoader.VIDEO;
};
- // protected methods
- /**
- * The result formatter for SVG files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {Object}
- * @private
- */
- p._formatResult = function (loader) {
- // mime should be image/svg+xml, but Opera requires text/xml
- var xml = createjs.DataUtils.parseXML(loader.getResult(true), "text/xml");
- var tag = loader.getTag();
+ createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader");
- if (!this._preferXHR && document.body.contains(tag)) {
- document.body.removeChild(tag);
- }
+}(scope.createjs));
- if (xml.documentElement != null) {
- tag.appendChild(xml.documentElement);
- tag.style.visibility = "visible";
- return tag;
- } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8)
- return xml;
- }
- };
+//##############################################################################
+// SpriteSheetLoader.js
+//##############################################################################
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for EaselJS SpriteSheets. Images inside the spritesheet definition are loaded before the loader
+ * completes. To load SpriteSheets using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}}
+ * as part of the {{#crossLink "LoadItem"}}{{/crossLink}}. Note that the {{#crossLink "JSONLoader"}}{{/crossLink}}
+ * and {{#crossLink "JSONPLoader"}}{{/crossLink}} are higher priority loaders, so SpriteSheets must
+ * set the {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property
+ * to {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}.
+ *
+ * The {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/crossOrigin:property"}}{{/crossLink}} as well
+ * as the {{#crossLink "LoadQueue's"}}{{/crossLink}} `basePath` argument and {{#crossLink "LoadQueue/_preferXHR"}}{{/crossLink}}
+ * property supplied to the {{#crossLink "LoadQueue"}}{{/crossLink}} are passed on to the sub-manifest that loads
+ * the SpriteSheet images.
+ *
+ * Note that the SpriteSheet JSON does not respect the {{#crossLink "LoadQueue/_preferXHR:property"}}{{/crossLink}}
+ * property, which should instead be determined by the presence of a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}}
+ * property on the SpriteSheet load item. This is because the JSON loaded will have a different format depending on
+ * if it is loaded as JSON, so just changing `preferXHR` is not enough to change how it is loaded.
+ * @class SpriteSheetLoader
+ * @param {LoadItem|Object} loadItem
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function SpriteSheetLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SPRITESHEET);
+
+ // protected properties
+ /**
+ * An internal queue which loads the SpriteSheet's images.
+ * @method _manifestQueue
+ * @type {LoadQueue}
+ * @private
+ */
+ this._manifestQueue = null;
+ }
+
+ var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader);
+ var s = SpriteSheetLoader;
+
+ // static properties
+ /**
+ * The amount of progress that the manifest itself takes up.
+ * @property SPRITESHEET_PROGRESS
+ * @type {number}
+ * @default 0.25 (25%)
+ * @private
+ * @static
+ */
+ s.SPRITESHEET_PROGRESS = 0.25;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.SPRITESHEET;
+ };
+
+ // public methods
+ p.destroy = function() {
+ this.AbstractLoader_destroy;
+ this._manifestQueue.close();
+ };
+
+ // protected methods
+ p._createRequest = function() {
+ var callback = this._item.callback;
+ if (callback != null) {
+ this._request = new createjs.JSONPLoader(this._item);
+ } else {
+ this._request = new createjs.JSONLoader(this._item);
+ }
+ };
+
+ p.handleEvent = function (event) {
+ switch (event.type) {
+ case "complete":
+ this._rawResult = event.target.getResult(true);
+ this._result = event.target.getResult();
+ this._sendProgress(s.SPRITESHEET_PROGRESS);
+ this._loadManifest(this._result);
+ return;
+ case "progress":
+ event.loaded *= s.SPRITESHEET_PROGRESS;
+ this.progress = event.loaded / event.total;
+ if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
+ this._sendProgress(event);
+ return;
+ }
+ this.AbstractLoader_handleEvent(event);
+ };
+
+ /**
+ * Create and load the images once the SpriteSheet JSON has been loaded.
+ * @method _loadManifest
+ * @param {Object} json
+ * @private
+ */
+ p._loadManifest = function (json) {
+ if (json && json.images) {
+ var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR, this._item.path, this._item.crossOrigin);
+ queue.on("complete", this._handleManifestComplete, this, true);
+ queue.on("fileload", this._handleManifestFileLoad, this);
+ queue.on("progress", this._handleManifestProgress, this);
+ queue.on("error", this._handleManifestError, this, true);
+ queue.loadManifest(json.images);
+ }
+ };
+
+ /**
+ * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed.
+ * @method _handleManifestFileLoad
+ * @param {Event} event
+ * @private
+ */
+ p._handleManifestFileLoad = function (event) {
+ var image = event.result;
+ if (image != null) {
+ var images = this.getResult().images;
+ var pos = images.indexOf(event.item.src);
+ images[pos] = image;
+ }
+ };
+
+ /**
+ * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
+ * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader.
+ * @method _handleManifestComplete
+ * @param {Event} event
+ * @private
+ */
+ p._handleManifestComplete = function (event) {
+ this._result = new createjs.SpriteSheet(this._result);
+ this._loadedItems = this._manifestQueue.getItems(true);
+ this._sendComplete();
+ };
+
+ /**
+ * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress.
+ * @method _handleManifestProgress
+ * @param {ProgressEvent} event
+ * @private
+ */
+ p._handleManifestProgress = function (event) {
+ this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS;
+ this._sendProgress(this.progress);
+ };
+
+ /**
+ * An image has reported an error.
+ * @method _handleManifestError
+ * @param {ErrorEvent} event
+ * @private
+ */
+ p._handleManifestError = function (event) {
+ var newEvent = new createjs.Event("fileerror");
+ newEvent.item = event.data;
+ this.dispatchEvent(newEvent);
+ };
+
+ createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader");
+
+}(scope.createjs));
- createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader");
+//##############################################################################
+// SVGLoader.js
+//##############################################################################
-}());
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
+ "use strict";
+
+ // constructor
+ /**
+ * A loader for SVG files.
+ * @class SVGLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractLoader
+ * @constructor
+ */
+ function SVGLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SVG);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "data";
+
+ if (preferXHR) {
+ this.setTag(document.createElement("svg"));
+ } else {
+ this.setTag(document.createElement("object"));
+ this.getTag().type = "image/svg+xml";
+ }
+ };
+
+ var p = createjs.extend(SVGLoader, createjs.AbstractLoader);
+ var s = SVGLoader;
+
+ // static methods
+ /**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+ s.canLoadItem = function (item) {
+ return item.type == createjs.AbstractLoader.SVG;
+ };
+
+ // protected methods
+ /**
+ * The result formatter for SVG files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {Object}
+ * @private
+ */
+ p._formatResult = function (loader) {
+ // mime should be image/svg+xml, but Opera requires text/xml
+ var xml = createjs.DataUtils.parseXML(loader.getResult(true), "text/xml");
+ var tag = loader.getTag();
+
+ if (!this._preferXHR && document.body.contains(tag)) {
+ document.body.removeChild(tag);
+ }
+
+ if (xml.documentElement != null) {
+ tag.appendChild(xml.documentElement);
+ tag.style.visibility = "visible";
+ return tag;
+ } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8)
+ return xml;
+ }
+ };
+
+ createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader");
+
+}(scope.createjs));
//##############################################################################
// XMLLoader.js
//##############################################################################
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -7254,4 +7317,4 @@ this.createjs = this.createjs || {};
createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader");
-}());
\ No newline at end of file
+}(scope.createjs));
\ No newline at end of file
diff --git a/lib/preloadjs-NEXT.min.js b/lib/preloadjs-NEXT.min.js
index 545d6e9..02415a9 100644
--- a/lib/preloadjs-NEXT.min.js
+++ b/lib/preloadjs-NEXT.min.js
@@ -9,5 +9,5 @@
*
* This notice shall be included in all copies or substantial portions of the Software.
*/
-this.createjs=this.createjs||{},function(){"use strict";var a=createjs.PreloadJS=createjs.PreloadJS||{};a.version="NEXT",a.buildDate="Thu, 22 Oct 2015 16:01:29 GMT"}(),this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1},this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},function(){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var a=Event.prototype;a.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},a.stopPropagation=function(){this.propagationStopped=!0},a.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},a.remove=function(){this.removed=!0},a.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=Event}(),this.createjs=this.createjs||{},function(){"use strict";function ErrorEvent(a,b,c){this.Event_constructor("error"),this.title=a,this.message=b,this.data=c}var a=createjs.extend(ErrorEvent,createjs.Event);a.clone=function(){return new createjs.ErrorEvent(this.title,this.message,this.data)},createjs.ErrorEvent=createjs.promote(ErrorEvent,"Event")}(),this.createjs=this.createjs||{},function(){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var a=EventDispatcher.prototype;EventDispatcher.initialize=function(b){b.addEventListener=a.addEventListener,b.on=a.on,b.removeEventListener=b.off=a.removeEventListener,b.removeAllEventListeners=a.removeAllEventListeners,b.hasEventListener=a.hasEventListener,b.dispatchEvent=a.dispatchEvent,b._dispatchEvent=a._dispatchEvent,b.willTrigger=a.willTrigger},a.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},a.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},a.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},a.off=a.removeEventListener,a.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},a.dispatchEvent=function(a){if("string"==typeof a){var b=this._listeners;if(!b||!b[a])return!1;a=new createjs.Event(a)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(c){}if(a.bubbles&&this.parent){for(var d=this,e=[d];d.parent;)e.push(d=d.parent);var f,g=e.length;for(f=g-1;f>=0&&!a.propagationStopped;f--)e[f]._dispatchEvent(a,1+(0==f));for(f=1;g>f&&!a.propagationStopped;f++)e[f]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return a.defaultPrevented},a.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},a.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},a.toString=function(){return"[EventDispatcher]"},a._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;try{a.currentTarget=this}catch(f){}try{a.eventPhase=b}catch(f){}a.removed=!1,e=e.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=e[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}},createjs.EventDispatcher=EventDispatcher}(),this.createjs=this.createjs||{},function(){"use strict";function ProgressEvent(a,b){this.Event_constructor("progress"),this.loaded=a,this.total=null==b?1:b,this.progress=0==b?0:this.loaded/this.total}var a=createjs.extend(ProgressEvent,createjs.Event);a.clone=function(){return new createjs.ProgressEvent(this.loaded,this.total)},createjs.ProgressEvent=createjs.promote(ProgressEvent,"Event")}(window),function(){function a(b,d){function f(a){if(f[a]!==q)return f[a];var b;if("bug-string-char-index"==a)b="a"!="a"[0];else if("json"==a)b=f("json-stringify")&&f("json-parse");else{var c,e='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==a){var i=d.stringify,k="function"==typeof i&&t;if(k){(c=function(){return 1}).toJSON=c;try{k="0"===i(0)&&"0"===i(new g)&&'""'==i(new h)&&i(s)===q&&i(q)===q&&i()===q&&"1"===i(c)&&"[1]"==i([c])&&"[null]"==i([q])&&"null"==i(null)&&"[null,null,null]"==i([q,s,null])&&i({a:[c,!0,!1,null,"\x00\b\n\f\r "]})==e&&"1"===i(null,c)&&"[\n 1,\n 2\n]"==i([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==i(new j(-864e13))&&'"+275760-09-13T00:00:00.000Z"'==i(new j(864e13))&&'"-000001-01-01T00:00:00.000Z"'==i(new j(-621987552e5))&&'"1969-12-31T23:59:59.999Z"'==i(new j(-1))}catch(l){k=!1}}b=k}if("json-parse"==a){var m=d.parse;if("function"==typeof m)try{if(0===m("0")&&!m(!1)){c=m(e);var n=5==c.a.length&&1===c.a[0];if(n){try{n=!m('" "')}catch(l){}if(n)try{n=1!==m("01")}catch(l){}if(n)try{n=1!==m("1.")}catch(l){}}}}catch(l){n=!1}b=n}}return f[a]=!!b}b||(b=e.Object()),d||(d=e.Object());var g=b.Number||e.Number,h=b.String||e.String,i=b.Object||e.Object,j=b.Date||e.Date,k=b.SyntaxError||e.SyntaxError,l=b.TypeError||e.TypeError,m=b.Math||e.Math,n=b.JSON||e.JSON;"object"==typeof n&&n&&(d.stringify=n.stringify,d.parse=n.parse);var o,p,q,r=i.prototype,s=r.toString,t=new j(-0xc782b5b800cec);try{t=-109252==t.getUTCFullYear()&&0===t.getUTCMonth()&&1===t.getUTCDate()&&10==t.getUTCHours()&&37==t.getUTCMinutes()&&6==t.getUTCSeconds()&&708==t.getUTCMilliseconds()}catch(u){}if(!f("json")){var v="[object Function]",w="[object Date]",x="[object Number]",y="[object String]",z="[object Array]",A="[object Boolean]",B=f("bug-string-char-index");if(!t)var C=m.floor,D=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,b){return D[b]+365*(a-1970)+C((a-1969+(b=+(b>1)))/4)-C((a-1901+b)/100)+C((a-1601+b)/400)};if((o=r.hasOwnProperty)||(o=function(a){var b,c={};return(c.__proto__=null,c.__proto__={toString:1},c).toString!=s?o=function(a){var b=this.__proto__,c=a in(this.__proto__=null,this);return this.__proto__=b,c}:(b=c.constructor,o=function(a){var c=(this.constructor||b).prototype;return a in this&&!(a in c&&this[a]===c[a])}),c=null,o.call(this,a)}),p=function(a,b){var d,e,f,g=0;(d=function(){this.valueOf=0}).prototype.valueOf=0,e=new d;for(f in e)o.call(e,f)&&g++;return d=e=null,g?p=2==g?function(a,b){var c,d={},e=s.call(a)==v;for(c in a)e&&"prototype"==c||o.call(d,c)||!(d[c]=1)||!o.call(a,c)||b(c)}:function(a,b){var c,d,e=s.call(a)==v;for(c in a)e&&"prototype"==c||!o.call(a,c)||(d="constructor"===c)||b(c);(d||o.call(a,c="constructor"))&&b(c)}:(e=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],p=function(a,b){var d,f,g=s.call(a)==v,h=!g&&"function"!=typeof a.constructor&&c[typeof a.hasOwnProperty]&&a.hasOwnProperty||o;for(d in a)g&&"prototype"==d||!h.call(a,d)||b(d);for(f=e.length;d=e[--f];h.call(a,d)&&b(d));}),p(a,b)},!f("json-stringify")){var F={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},G="000000",H=function(a,b){return(G+(b||0)).slice(-a)},I="\\u00",J=function(a){for(var b='"',c=0,d=a.length,e=!B||d>10,f=e&&(B?a.split(""):a);d>c;c++){var g=a.charCodeAt(c);switch(g){case 8:case 9:case 10:case 12:case 13:case 34:case 92:b+=F[g];break;default:if(32>g){b+=I+H(2,g.toString(16));break}b+=e?f[c]:a.charAt(c)}}return b+'"'},K=function(a,b,c,d,e,f,g){var h,i,j,k,m,n,r,t,u,v,B,D,F,G,I,L;try{h=b[a]}catch(M){}if("object"==typeof h&&h)if(i=s.call(h),i!=w||o.call(h,"toJSON"))"function"==typeof h.toJSON&&(i!=x&&i!=y&&i!=z||o.call(h,"toJSON"))&&(h=h.toJSON(a));else if(h>-1/0&&1/0>h){if(E){for(m=C(h/864e5),j=C(m/365.2425)+1970-1;E(j+1,0)<=m;j++);for(k=C((m-E(j,0))/30.42);E(j,k+1)<=m;k++);m=1+m-E(j,k),n=(h%864e5+864e5)%864e5,r=C(n/36e5)%24,t=C(n/6e4)%60,u=C(n/1e3)%60,v=n%1e3}else j=h.getUTCFullYear(),k=h.getUTCMonth(),m=h.getUTCDate(),r=h.getUTCHours(),t=h.getUTCMinutes(),u=h.getUTCSeconds(),v=h.getUTCMilliseconds();h=(0>=j||j>=1e4?(0>j?"-":"+")+H(6,0>j?-j:j):H(4,j))+"-"+H(2,k+1)+"-"+H(2,m)+"T"+H(2,r)+":"+H(2,t)+":"+H(2,u)+"."+H(3,v)+"Z"}else h=null;if(c&&(h=c.call(b,a,h)),null===h)return"null";if(i=s.call(h),i==A)return""+h;if(i==x)return h>-1/0&&1/0>h?""+h:"null";if(i==y)return J(""+h);if("object"==typeof h){for(G=g.length;G--;)if(g[G]===h)throw l();if(g.push(h),B=[],I=f,f+=e,i==z){for(F=0,G=h.length;G>F;F++)D=K(F,h,c,d,e,f,g),B.push(D===q?"null":D);L=B.length?e?"[\n"+f+B.join(",\n"+f)+"\n"+I+"]":"["+B.join(",")+"]":"[]"}else p(d||h,function(a){var b=K(a,h,c,d,e,f,g);b!==q&&B.push(J(a)+":"+(e?" ":"")+b)}),L=B.length?e?"{\n"+f+B.join(",\n"+f)+"\n"+I+"}":"{"+B.join(",")+"}":"{}";return g.pop(),L}};d.stringify=function(a,b,d){var e,f,g,h;if(c[typeof b]&&b)if((h=s.call(b))==v)f=b;else if(h==z){g={};for(var i,j=0,k=b.length;k>j;i=b[j++],h=s.call(i),(h==y||h==x)&&(g[i]=1));}if(d)if((h=s.call(d))==x){if((d-=d%1)>0)for(e="",d>10&&(d=10);e.lengthL;)switch(e=f.charCodeAt(L)){case 9:case 10:case 13:case 32:L++;break;case 123:case 125:case 91:case 93:case 58:case 44:return a=B?f.charAt(L):f[L],L++,a;case 34:for(a="@",L++;g>L;)if(e=f.charCodeAt(L),32>e)P();else if(92==e)switch(e=f.charCodeAt(++L)){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:a+=O[e],L++;break;case 117:for(b=++L,c=L+4;c>L;L++)e=f.charCodeAt(L),e>=48&&57>=e||e>=97&&102>=e||e>=65&&70>=e||P();a+=N("0x"+f.slice(b,L));break;default:P()}else{if(34==e)break;for(e=f.charCodeAt(L),b=L;e>=32&&92!=e&&34!=e;)e=f.charCodeAt(++L);a+=f.slice(b,L)}if(34==f.charCodeAt(L))return L++,a;P();default:if(b=L,45==e&&(d=!0,e=f.charCodeAt(++L)),e>=48&&57>=e){for(48==e&&(e=f.charCodeAt(L+1),e>=48&&57>=e)&&P(),d=!1;g>L&&(e=f.charCodeAt(L),e>=48&&57>=e);L++);if(46==f.charCodeAt(L)){for(c=++L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}if(e=f.charCodeAt(L),101==e||69==e){for(e=f.charCodeAt(++L),(43==e||45==e)&&L++,c=L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}return+f.slice(b,L)}if(d&&P(),"true"==f.slice(L,L+4))return L+=4,!0;if("false"==f.slice(L,L+5))return L+=5,!1;if("null"==f.slice(L,L+4))return L+=4,null;P()}return"$"},R=function(a){var b,c;if("$"==a&&P(),"string"==typeof a){if("@"==(B?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(b=[];a=Q(),"]"!=a;c||(c=!0))c&&(","==a?(a=Q(),"]"==a&&P()):P()),","==a&&P(),b.push(R(a));return b}if("{"==a){for(b={};a=Q(),"}"!=a;c||(c=!0))c&&(","==a?(a=Q(),"}"==a&&P()):P()),(","==a||"string"!=typeof a||"@"!=(B?a.charAt(0):a[0])||":"!=Q())&&P(),b[a.slice(1)]=R(Q());return b}P()}return a},S=function(a,b,c){var d=T(a,b,c);d===q?delete a[b]:a[b]=d},T=function(a,b,c){var d,e=a[b];if("object"==typeof e&&e)if(s.call(e)==z)for(d=e.length;d--;)S(e,d,c);else p(e,function(a){S(e,a,c)});return c.call(a,b,e)};d.parse=function(a,b){var c,d;return L=0,M=""+a,c=R(Q()),"$"!=Q()&&P(),L=M=null,b&&s.call(b)==v?T((d={},d[""]=c,d),"",b):c}}}return d.runInContext=a,d}var b="function"==typeof define&&define.amd,c={"function":!0,object:!0},d=c[typeof exports]&&exports&&!exports.nodeType&&exports,e=c[typeof window]&&window||this,f=d&&c[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;if(!f||f.global!==f&&f.window!==f&&f.self!==f||(e=f),d&&!b)a(e,d);else{var g=e.JSON,h=e.JSON3,i=!1,j=a(e,e.JSON3={noConflict:function(){return i||(i=!0,e.JSON=g,e.JSON3=h,g=h=null),j}});e.JSON={parse:j.parse,stringify:j.stringify}}b&&define(function(){return j})}.call(this),function(){var a={};a.appendToHead=function(b){a.getHead().appendChild(b)},a.getHead=function(){return document.head||document.getElementsByTagName("head")[0]},a.getBody=function(){return document.body||document.getElementsByTagName("body")[0]},createjs.DomUtils=a}(),function(){var a={};a.parseXML=function(a,b){var c=null;try{if(window.DOMParser){var d=new DOMParser;c=d.parseFromString(a,b)}}catch(e){}if(!c)try{c=new ActiveXObject("Microsoft.XMLDOM"),c.async=!1,c.loadXML(a)}catch(e){c=null}return c},a.parseJSON=function(a){if(null==a)return null;try{return JSON.parse(a)}catch(b){throw b}},createjs.DataUtils=a}(),this.createjs=this.createjs||{},function(){"use strict";function LoadItem(){this.src=null,this.type=null,this.id=null,this.maintainOrder=!1,this.callback=null,this.data=null,this.method=createjs.LoadItem.GET,this.values=null,this.headers=null,this.withCredentials=!1,this.mimeType=null,this.crossOrigin=null,this.loadTimeout=b.LOAD_TIMEOUT_DEFAULT}var a=LoadItem.prototype={},b=LoadItem;b.LOAD_TIMEOUT_DEFAULT=8e3,b.create=function(a){if("string"==typeof a){var c=new LoadItem;return c.src=a,c}if(a instanceof b)return a;if(a instanceof Object&&a.src)return null==a.loadTimeout&&(a.loadTimeout=b.LOAD_TIMEOUT_DEFAULT),a;throw new Error("Type not recognized.")},a.set=function(a){for(var b in a)this[b]=a[b];return this},createjs.LoadItem=b}(),function(){var a={};a.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,a.RELATIVE_PATT=/^[.\/]*?\//i,a.EXTENSION_PATT=/\/?[^\/]+\.(\w{1,5})$/i,a.parseURI=function(b){var c={absolute:!1,relative:!1};if(null==b)return c;var d=b.indexOf("?");d>-1&&(b=b.substr(0,d));var e;return a.ABSOLUTE_PATT.test(b)?c.absolute=!0:a.RELATIVE_PATT.test(b)&&(c.relative=!0),(e=b.match(a.EXTENSION_PATT))&&(c.extension=e[1].toLowerCase()),c},a.formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},a.buildPath=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this._formatQueryString(b,c):a+"?"+this._formatQueryString(b,c)},a.isCrossDomain=function(a){var b=document.createElement("a");b.href=a.src;var c=document.createElement("a");c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},a.isLocal=function(a){var b=document.createElement("a");return b.href=a.src,""==b.hostname&&"file:"==b.protocol},a.isBinary=function(a){switch(a){case createjs.AbstractLoader.IMAGE:case createjs.AbstractLoader.BINARY:return!0;default:return!1}},a.isImageTag=function(a){return a instanceof HTMLImageElement},a.isAudioTag=function(a){return window.HTMLAudioElement?a instanceof HTMLAudioElement:!1},a.isVideoTag=function(a){return window.HTMLVideoElement?a instanceof HTMLVideoElement:!1},a.isText=function(a){switch(a){case createjs.AbstractLoader.TEXT:case createjs.AbstractLoader.JSON:case createjs.AbstractLoader.MANIFEST:case createjs.AbstractLoader.XML:case createjs.AbstractLoader.CSS:case createjs.AbstractLoader.SVG:case createjs.AbstractLoader.JAVASCRIPT:case createjs.AbstractLoader.SPRITESHEET:return!0;default:return!1}},a.getTypeByExtension=function(a){if(null==a)return createjs.AbstractLoader.TEXT;switch(a.toLowerCase()){case"jpeg":case"jpg":case"gif":case"png":case"webp":case"bmp":return createjs.AbstractLoader.IMAGE;case"ogg":case"mp3":case"webm":return createjs.AbstractLoader.SOUND;case"mp4":case"webm":case"ts":return createjs.AbstractLoader.VIDEO;case"json":return createjs.AbstractLoader.JSON;case"xml":return createjs.AbstractLoader.XML;case"css":return createjs.AbstractLoader.CSS;case"js":return createjs.AbstractLoader.JAVASCRIPT;case"svg":return createjs.AbstractLoader.SVG;default:return createjs.AbstractLoader.TEXT}},createjs.RequestUtils=a}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractLoader(a,b,c){this.EventDispatcher_constructor(),this.loaded=!1,this.canceled=!1,this.progress=0,this.type=c,this.resultFormatter=null,this._item=a?createjs.LoadItem.create(a):null,this._preferXHR=b,this._result=null,this._rawResult=null,this._loadedItems=null,this._tagSrcAttribute=null,this._tag=null}var a=createjs.extend(AbstractLoader,createjs.EventDispatcher),b=AbstractLoader;b.POST="POST",b.GET="GET",b.BINARY="binary",b.CSS="css",b.IMAGE="image",b.JAVASCRIPT="javascript",b.JSON="json",b.JSONP="jsonp",b.MANIFEST="manifest",b.SOUND="sound",b.VIDEO="video",b.SPRITESHEET="spritesheet",b.SVG="svg",b.TEXT="text",b.XML="xml",a.getItem=function(){return this._item},a.getResult=function(a){return a?this._rawResult:this._result},a.getTag=function(){return this._tag},a.setTag=function(a){this._tag=a},a.load=function(){this._createRequest(),this._request.on("complete",this,this),this._request.on("progress",this,this),this._request.on("loadStart",this,this),this._request.on("abort",this,this),this._request.on("timeout",this,this),this._request.on("error",this,this);var a=new createjs.Event("initialize");a.loader=this._request,this.dispatchEvent(a),this._request.load()},a.cancel=function(){this.canceled=!0,this.destroy()},a.destroy=function(){this._request&&(this._request.removeAllEventListeners(),this._request.destroy()),this._request=null,this._item=null,this._rawResult=null,this._result=null,this._loadItems=null,this.removeAllEventListeners()},a.getLoadedItems=function(){return this._loadedItems},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.TagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._createTag=function(){return null},a._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},a._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.ProgressEvent(this.progress)):(b=a,this.progress=a.loaded/a.total,b.progress=this.progress,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),this.hasEventListener("progress")&&this.dispatchEvent(b)}},a._sendComplete=function(){if(!this._isCanceled()){this.loaded=!0;var a=new createjs.Event("complete");a.rawResult=this._rawResult,null!=this._result&&(a.result=this._result),this.dispatchEvent(a)}},a._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY")),this.dispatchEvent(a))},a._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},a.resultFormatter=null,a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response;var b=this.resultFormatter&&this.resultFormatter(this);b instanceof Function?b.call(this,createjs.proxy(this._resultFormatSuccess,this),createjs.proxy(this._resultFormatFailed,this)):(this._result=b||this._rawResult,this._sendComplete());break;case"progress":this._sendProgress(a);break;case"error":this._sendError(a);break;case"loadstart":this._sendLoadStart();break;case"abort":case"timeout":this._isCanceled()||this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_"+a.type.toUpperCase()+"_ERROR"))}},a._resultFormatSuccess=function(a){this._result=a,this._sendComplete()},a._resultFormatFailed=function(a){this._sendError(a)},a.buildPath=function(a,b){return createjs.RequestUtils.buildPath(a,b)},a.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=createjs.promote(AbstractLoader,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractMediaLoader(a,b,c){this.AbstractLoader_constructor(a,b,c),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.on("initialize",this._updateXHR,this)}var a=createjs.extend(AbstractMediaLoader,createjs.AbstractLoader);a.load=function(){this._tag||(this._tag=this._createTag(this._item.src)),this._tag.preload="auto",this._tag.load(),this.AbstractLoader_load()},a._createTag=function(){},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.MediaTagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._updateXHR=function(a){a.loader.setResponseType&&a.loader.setResponseType("blob")},a._formatResult=function(a){if(this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.onstalled=null,this._preferXHR){var b=window.URL||window.webkitURL,c=a.getResult(!0);a.getTag().src=b.createObjectURL(c)}return a.getTag()},createjs.AbstractMediaLoader=createjs.promote(AbstractMediaLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractRequest=function(a){this._item=a},a=createjs.extend(AbstractRequest,createjs.EventDispatcher);a.load=function(){},a.destroy=function(){},a.cancel=function(){},createjs.AbstractRequest=createjs.promote(AbstractRequest,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function TagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this),this._addedToDOM=!1,this._startTagVisibility=null}var a=createjs.extend(TagRequest,createjs.AbstractRequest);a.load=function(){this._tag.onload=createjs.proxy(this._handleTagComplete,this),this._tag.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this),this._tag.onerror=createjs.proxy(this._handleError,this);var a=new createjs.Event("initialize");a.loader=this._tag,this.dispatchEvent(a),this._hideTag(),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag[this._tagSrcAttribute]=this._item.src,null==this._tag.parentNode&&(window.document.body.appendChild(this._tag),this._addedToDOM=!0)},a.destroy=function(){this._clean(),this._tag=null,this.AbstractRequest_destroy()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleError=function(){this._clean(),this.dispatchEvent("error")},a._handleTagComplete=function(){this._rawResult=this._tag,this._result=this.resultFormatter&&this.resultFormatter(this)||this._rawResult,this._clean(),this._showTag(),this.dispatchEvent("complete")},a._handleTimeout=function(){this._clean(),this.dispatchEvent(new createjs.Event("timeout"))},a._clean=function(){this._tag.onload=null,this._tag.onreadystatechange=null,this._tag.onerror=null,this._addedToDOM&&null!=this._tag.parentNode&&this._tag.parentNode.removeChild(this._tag),clearTimeout(this._loadTimeout)},a._hideTag=function(){this._startTagVisibility=this._tag.style.visibility,this._tag.style.visibility="hidden"},a._showTag=function(){this._tag.style.visibility=this._startTagVisibility},a._handleStalled=function(){},createjs.TagRequest=createjs.promote(TagRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function MediaTagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this)}var a=createjs.extend(MediaTagRequest,createjs.TagRequest);a.load=function(){var a=createjs.proxy(this._handleStalled,this);this._stalledCallback=a;var b=createjs.proxy(this._handleProgress,this);this._handleProgress=b,this._tag.addEventListener("stalled",a),this._tag.addEventListener("progress",b),this._tag.addEventListener&&this._tag.addEventListener("canplaythrough",this._loadedHandler,!1),this.TagRequest_load()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleStalled=function(){},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._clean=function(){this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.removeEventListener("stalled",this._stalledCallback),this._tag.removeEventListener("progress",this._progressCallback),this.TagRequest__clean()},createjs.MediaTagRequest=createjs.promote(MediaTagRequest,"TagRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function XHRRequest(a){this.AbstractRequest_constructor(a),this._request=null,this._loadTimeout=null,this._xhrLevel=1,this._response=null,this._rawResponse=null,this._canceled=!1,this._handleLoadStartProxy=createjs.proxy(this._handleLoadStart,this),this._handleProgressProxy=createjs.proxy(this._handleProgress,this),this._handleAbortProxy=createjs.proxy(this._handleAbort,this),this._handleErrorProxy=createjs.proxy(this._handleError,this),this._handleTimeoutProxy=createjs.proxy(this._handleTimeout,this),this._handleLoadProxy=createjs.proxy(this._handleLoad,this),this._handleReadyStateChangeProxy=createjs.proxy(this._handleReadyStateChange,this),!this._createXHR(a)}var a=createjs.extend(XHRRequest,createjs.AbstractRequest);XHRRequest.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],a.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},a.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},a.load=function(){if(null==this._request)return void this._handleError();null!=this._request.addEventListener?(this._request.addEventListener("loadstart",this._handleLoadStartProxy,!1),this._request.addEventListener("progress",this._handleProgressProxy,!1),this._request.addEventListener("abort",this._handleAbortProxy,!1),this._request.addEventListener("error",this._handleErrorProxy,!1),this._request.addEventListener("timeout",this._handleTimeoutProxy,!1),this._request.addEventListener("load",this._handleLoadProxy,!1),this._request.addEventListener("readystatechange",this._handleReadyStateChangeProxy,!1)):(this._request.onloadstart=this._handleLoadStartProxy,this._request.onprogress=this._handleProgressProxy,this._request.onabort=this._handleAbortProxy,this._request.onerror=this._handleErrorProxy,this._request.ontimeout=this._handleTimeoutProxy,this._request.onload=this._handleLoadProxy,this._request.onreadystatechange=this._handleReadyStateChangeProxy),1==this._xhrLevel&&(this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout));try{this._item.values&&this._item.method!=createjs.AbstractLoader.GET?this._item.method==createjs.AbstractLoader.POST&&this._request.send(createjs.RequestUtils.formatQueryString(this._item.values)):this._request.send()}catch(a){this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND",null,a))}},a.setResponseType=function(a){"blob"===a&&(a=window.URL?"blob":"arraybuffer",this._responseType=a),this._request.responseType=a},a.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},a.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._handleLoadStart=function(){clearTimeout(this._loadTimeout),this.dispatchEvent("loadstart")},a._handleAbort=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED",null,a))},a._handleError=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent(a.message))},a._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},a._handleLoad=function(){if(!this.loaded){this.loaded=!0;var a=this._checkError();if(a)return void this._handleError(a);if(this._response=this._getResponse(),"arraybuffer"===this._responseType)try{this._response=new Blob([this._response])}catch(b){if(window.BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,"TypeError"===b.name&&window.BlobBuilder){var c=new BlobBuilder;c.append(this._response),this._response=c.getBlob()}}this._clean(),this.dispatchEvent(new createjs.Event("complete"))}},a._handleTimeout=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT",null,a))},a._checkError=function(){var a=parseInt(this._request.status);switch(a){case 404:case 0:return new Error(a)}return null},a._getResponse=function(){if(null!=this._response)return this._response;if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},a._createXHR=function(a){var b=createjs.RequestUtils.isCrossDomain(a),c={},d=null;if(window.XMLHttpRequest)d=new XMLHttpRequest,b&&void 0===d.withCredentials&&window.XDomainRequest&&(d=new XDomainRequest);else{for(var e=0,f=s.ACTIVEX_VERSIONS.length;f>e;e++){var g=s.ACTIVEX_VERSIONS[e];try{d=new ActiveXObject(g);break}catch(h){}}if(null==d)return!1}null==a.mimeType&&createjs.RequestUtils.isText(a.type)&&(a.mimeType="text/plain; charset=utf-8"),a.mimeType&&d.overrideMimeType&&d.overrideMimeType(a.mimeType),this._xhrLevel="string"==typeof d.responseType?2:1;var i=null;if(i=a.method==createjs.AbstractLoader.GET?createjs.RequestUtils.buildPath(a.src,a.values):a.src,d.open(a.method||createjs.AbstractLoader.GET,i,!0),b&&d instanceof XMLHttpRequest&&1==this._xhrLevel&&(c.Origin=location.origin),a.values&&a.method==createjs.AbstractLoader.POST&&(c["Content-Type"]="application/x-www-form-urlencoded"),b||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest"),a.headers)for(var j in a.headers)c[j]=a.headers[j];for(j in c)d.setRequestHeader(j,c[j]);return d instanceof XMLHttpRequest&&void 0!==a.withCredentials&&(d.withCredentials=a.withCredentials),this._request=d,!0},a._clean=function(){clearTimeout(this._loadTimeout),null!=this._request.removeEventListener?(this._request.removeEventListener("loadstart",this._handleLoadStartProxy),this._request.removeEventListener("progress",this._handleProgressProxy),this._request.removeEventListener("abort",this._handleAbortProxy),this._request.removeEventListener("error",this._handleErrorProxy),this._request.removeEventListener("timeout",this._handleTimeoutProxy),this._request.removeEventListener("load",this._handleLoadProxy),this._request.removeEventListener("readystatechange",this._handleReadyStateChangeProxy)):(this._request.onloadstart=null,this._request.onprogress=null,this._request.onabort=null,this._request.onerror=null,this._request.ontimeout=null,this._request.onload=null,this._request.onreadystatechange=null)},a.toString=function(){return"[PreloadJS XHRRequest]"},createjs.XHRRequest=createjs.promote(XHRRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function LoadQueue(a,b,c){this.AbstractLoader_constructor(),this._plugins=[],this._typeCallbacks={},this._extensionCallbacks={},this.next=null,this.maintainScriptOrder=!0,this.stopOnError=!1,this._maxConnections=1,this._availableLoaders=[createjs.ImageLoader,createjs.JavaScriptLoader,createjs.CSSLoader,createjs.JSONLoader,createjs.JSONPLoader,createjs.SoundLoader,createjs.ManifestLoader,createjs.SpriteSheetLoader,createjs.XMLLoader,createjs.SVGLoader,createjs.BinaryLoader,createjs.VideoLoader,createjs.TextLoader],this._defaultLoaderLength=this._availableLoaders.length,this.init(a,b,c)
-}var a=createjs.extend(LoadQueue,createjs.AbstractLoader),b=LoadQueue;a.init=function(a,b,c){this.useXHR=!0,this.preferXHR=!0,this._preferXHR=!0,this.setPreferXHR(a),this._paused=!1,this._basePath=b,this._crossOrigin=c,this._loadStartWasDispatched=!1,this._currentlyLoadingScript=null,this._currentLoads=[],this._loadQueue=[],this._loadQueueBackup=[],this._loadItemsById={},this._loadItemsBySrc={},this._loadedResults={},this._loadedRawResults={},this._numItems=0,this._numItemsLoaded=0,this._scriptOrder=[],this._loadedScripts=[],this._lastProgress=0/0},b.loadTimeout=8e3,b.LOAD_TIMEOUT=0,b.BINARY=createjs.AbstractLoader.BINARY,b.CSS=createjs.AbstractLoader.CSS,b.IMAGE=createjs.AbstractLoader.IMAGE,b.JAVASCRIPT=createjs.AbstractLoader.JAVASCRIPT,b.JSON=createjs.AbstractLoader.JSON,b.JSONP=createjs.AbstractLoader.JSONP,b.MANIFEST=createjs.AbstractLoader.MANIFEST,b.SOUND=createjs.AbstractLoader.SOUND,b.VIDEO=createjs.AbstractLoader.VIDEO,b.SVG=createjs.AbstractLoader.SVG,b.TEXT=createjs.AbstractLoader.TEXT,b.XML=createjs.AbstractLoader.XML,b.POST=createjs.AbstractLoader.POST,b.GET=createjs.AbstractLoader.GET,a.registerLoader=function(a){if(!a||!a.canLoadItem)throw new Error("loader is of an incorrect type.");if(-1!=this._availableLoaders.indexOf(a))throw new Error("loader already exists.");this._availableLoaders.unshift(a)},a.unregisterLoader=function(a){var b=this._availableLoaders.indexOf(a);-1!=b&&b0)return;var c=!1;if(b){for(;b.length;){var d=b.pop(),e=this.getResult(d);for(f=this._loadQueue.length-1;f>=0;f--)if(g=this._loadQueue[f].getItem(),g.id==d||g.src==d){this._loadQueue.splice(f,1)[0].cancel();break}for(f=this._loadQueueBackup.length-1;f>=0;f--)if(g=this._loadQueueBackup[f].getItem(),g.id==d||g.src==d){this._loadQueueBackup.splice(f,1)[0].cancel();break}if(e)this._disposeItem(this.getItem(d));else for(var f=this._currentLoads.length-1;f>=0;f--){var g=this._currentLoads[f].getItem();if(g.id==d||g.src==d){this._currentLoads.splice(f,1)[0].cancel(),c=!0;break}}}c&&this._loadNext()}else{this.close();for(var h in this._loadItemsById)this._disposeItem(this._loadItemsById[h]);this.init(this.preferXHR,this._basePath)}},a.reset=function(){this.close();for(var a in this._loadItemsById)this._disposeItem(this._loadItemsById[a]);for(var b=[],c=0,d=this._loadQueueBackup.length;d>c;c++)b.push(this._loadQueueBackup[c].getItem());this.loadManifest(b,!1)},a.installPlugin=function(a){if(null!=a&&null!=a.getPreloadHandlers){this._plugins.push(a);var b=a.getPreloadHandlers();if(b.scope=a,null!=b.types)for(var c=0,d=b.types.length;d>c;c++)this._typeCallbacks[b.types[c]]=b;if(null!=b.extensions)for(c=0,d=b.extensions.length;d>c;c++)this._extensionCallbacks[b.extensions[c]]=b}},a.setMaxConnections=function(a){this._maxConnections=a,!this._paused&&this._loadQueue.length>0&&this._loadNext()},a.loadFile=function(a,b,c){if(null==a){var d=new createjs.ErrorEvent("PRELOAD_NO_FILE");return void this._sendError(d)}this._addItem(a,null,c),this.setPaused(b!==!1?!1:!0)},a.loadManifest=function(a,c,d){var e=null,f=null;if(Array.isArray(a)){if(0==a.length){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");return void this._sendError(g)}e=a}else if("string"==typeof a)e=[{src:a,type:b.MANIFEST}];else{if("object"!=typeof a){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");return void this._sendError(g)}if(void 0!==a.src){if(null==a.type)a.type=b.MANIFEST;else if(a.type!=b.MANIFEST){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");this._sendError(g)}e=[a]}else void 0!==a.manifest&&(e=a.manifest,f=a.path)}for(var h=0,i=e.length;i>h;h++)this._addItem(e[h],f,d);this.setPaused(c!==!1?!1:!0)},a.load=function(){this.setPaused(!1)},a.getItem=function(a){return this._loadItemsById[a]||this._loadItemsBySrc[a]},a.getResult=function(a,b){var c=this._loadItemsById[a]||this._loadItemsBySrc[a];if(null==c)return null;var d=c.id;return b&&this._loadedRawResults[d]?this._loadedRawResults[d]:this._loadedResults[d]},a.getItems=function(a){var b=[];for(var c in this._loadItemsById){var d=this._loadItemsById[c],e=this.getResult(c);(a!==!0||null!=e)&&b.push({item:d,result:e,rawResult:this.getResult(c,!0)})}return b},a.setPaused=function(a){this._paused=a,this._paused||this._loadNext()},a.close=function(){for(;this._currentLoads.length;)this._currentLoads.pop().cancel();this._scriptOrder.length=0,this._loadedScripts.length=0,this.loadStartWasDispatched=!1,this._itemCount=0,this._lastProgress=0/0},a._addItem=function(a,b,c){var d=this._createLoadItem(a,b,c);if(null!=d){var e=this._createLoader(d);null!=e&&("plugins"in e&&(e.plugins=this._plugins),d._loader=e,this._loadQueue.push(e),this._loadQueueBackup.push(e),this._numItems++,this._updateProgress(),(this.maintainScriptOrder&&d.type==createjs.LoadQueue.JAVASCRIPT||d.maintainOrder===!0)&&(this._scriptOrder.push(d),this._loadedScripts.push(null)))}},a._createLoadItem=function(a,b,c){var d=createjs.LoadItem.create(a);if(null==d)return null;var e="",f=c||this._basePath;if(d.src instanceof Object){if(!d.type)return null;if(b){e=b;var g=createjs.RequestUtils.parseURI(b);null==f||g.absolute||g.relative||(e=f+e)}else null!=f&&(e=f)}else{var h=createjs.RequestUtils.parseURI(d.src);h.extension&&(d.ext=h.extension),null==d.type&&(d.type=createjs.RequestUtils.getTypeByExtension(d.ext));var i=d.src;if(!h.absolute&&!h.relative)if(b){e=b;var g=createjs.RequestUtils.parseURI(b);i=b+i,null==f||g.absolute||g.relative||(e=f+e)}else null!=f&&(e=f);d.src=e+d.src}d.path=e,(void 0===d.id||null===d.id||""===d.id)&&(d.id=i);var j=this._typeCallbacks[d.type]||this._extensionCallbacks[d.ext];if(j){var k=j.callback.call(j.scope,d,this);if(k===!1)return null;k===!0||null!=k&&(d._loader=k),h=createjs.RequestUtils.parseURI(d.src),null!=h.extension&&(d.ext=h.extension)}return this._loadItemsById[d.id]=d,this._loadItemsBySrc[d.src]=d,null==d.crossOrigin&&(d.crossOrigin=this._crossOrigin),d},a._createLoader=function(a){if(null!=a._loader)return a._loader;for(var b=this.preferXHR,c=0;c=this._maxConnections);a++){var b=this._loadQueue[a];this._canStartLoad(b)&&(this._loadQueue.splice(a,1),a--,this._loadItem(b))}}},a._loadItem=function(a){a.on("fileload",this._handleFileLoad,this),a.on("progress",this._handleProgress,this),a.on("complete",this._handleFileComplete,this),a.on("error",this._handleError,this),a.on("fileerror",this._handleFileError,this),this._currentLoads.push(a),this._sendFileStart(a.getItem()),a.load()},a._handleFileLoad=function(a){a.target=null,this.dispatchEvent(a)},a._handleFileError=function(a){var b=new createjs.ErrorEvent("FILE_LOAD_ERROR",null,a.item);this._sendError(b)},a._handleError=function(a){var b=a.target;this._numItemsLoaded++,this._finishOrderedItem(b,!0),this._updateProgress();var c=new createjs.ErrorEvent("FILE_LOAD_ERROR",null,b.getItem());this._sendError(c),this.stopOnError?this.setPaused(!0):(this._removeLoadItem(b),this._cleanLoadItem(b),this._loadNext())},a._handleFileComplete=function(a){var b=a.target,c=b.getItem(),d=b.getResult();this._loadedResults[c.id]=d;var e=b.getResult(!0);null!=e&&e!==d&&(this._loadedRawResults[c.id]=e),this._saveLoadedItems(b),this._removeLoadItem(b),this._finishOrderedItem(b)||this._processFinishedLoad(c,b),this._cleanLoadItem(b)},a._saveLoadedItems=function(a){var b=a.getLoadedItems();if(null!==b)for(var c=0;cb;b++){var c=this._loadedScripts[b];if(null===c)break;if(c!==!0){var d=this._loadedResults[c.id];c.type==createjs.LoadQueue.JAVASCRIPT&&createjs.DomUtils.appendToHead(d);var e=c._loader;this._processFinishedLoad(c,e),this._loadedScripts[b]=!0}}},a._processFinishedLoad=function(a,b){if(this._numItemsLoaded++,!this.maintainScriptOrder&&a.type==createjs.LoadQueue.JAVASCRIPT){var c=b.getTag();createjs.DomUtils.appendToHead(c)}this._updateProgress(),this._sendFileComplete(a,b),this._loadNext()},a._canStartLoad=function(a){if(!this.maintainScriptOrder||a.preferXHR)return!0;var b=a.getItem();if(b.type!=createjs.LoadQueue.JAVASCRIPT)return!0;if(this._currentlyLoadingScript)return!1;for(var c=this._scriptOrder.indexOf(b),d=0;c>d;){var e=this._loadedScripts[d];if(null==e)return!1;d++}return this._currentlyLoadingScript=!0,!0},a._removeLoadItem=function(a){for(var b=this._currentLoads.length,c=0;b>c;c++)if(this._currentLoads[c]==a){this._currentLoads.splice(c,1);break}},a._cleanLoadItem=function(a){var b=a.getItem();b&&delete b._loader},a._handleProgress=function(a){var b=a.target;this._sendFileProgress(b.getItem(),b.progress),this._updateProgress()},a._updateProgress=function(){var a=this._numItemsLoaded/this._numItems,b=this._numItems-this._numItemsLoaded;if(b>0){for(var c=0,d=0,e=this._currentLoads.length;e>d;d++)c+=this._currentLoads[d].progress;a+=c/b*(b/this._numItems)}this._lastProgress!=a&&(this._sendProgress(a),this._lastProgress=a)},a._disposeItem=function(a){delete this._loadedResults[a.id],delete this._loadedRawResults[a.id],delete this._loadItemsById[a.id],delete this._loadItemsBySrc[a.src]},a._sendFileProgress=function(a,b){if(!this._isCanceled()&&!this._paused&&this.hasEventListener("fileprogress")){var c=new createjs.Event("fileprogress");c.progress=b,c.loaded=b,c.total=1,c.item=a,this.dispatchEvent(c)}},a._sendFileComplete=function(a,b){if(!this._isCanceled()&&!this._paused){var c=new createjs.Event("fileload");c.loader=b,c.item=a,c.result=this._loadedResults[a.id],c.rawResult=this._loadedRawResults[a.id],a.completeHandler&&a.completeHandler(c),this.hasEventListener("fileload")&&this.dispatchEvent(c)}},a._sendFileStart=function(a){var b=new createjs.Event("filestart");b.item=a,this.hasEventListener("filestart")&&this.dispatchEvent(b)},a.toString=function(){return"[PreloadJS LoadQueue]"},createjs.LoadQueue=createjs.promote(LoadQueue,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function TextLoader(a){this.AbstractLoader_constructor(a,!0,createjs.AbstractLoader.TEXT)}var a=(createjs.extend(TextLoader,createjs.AbstractLoader),TextLoader);a.canLoadItem=function(a){return a.type==createjs.AbstractLoader.TEXT},createjs.TextLoader=createjs.promote(TextLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function BinaryLoader(a){this.AbstractLoader_constructor(a,!0,createjs.AbstractLoader.BINARY),this.on("initialize",this._updateXHR,this)}var a=createjs.extend(BinaryLoader,createjs.AbstractLoader),b=BinaryLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.BINARY},a._updateXHR=function(a){a.loader.setResponseType("arraybuffer")},createjs.BinaryLoader=createjs.promote(BinaryLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function CSSLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.AbstractLoader.CSS),this.resultFormatter=this._formatResult,this._tagSrcAttribute="href",this._tag=document.createElement(b?"style":"link"),this._tag.rel="stylesheet",this._tag.type="text/css"}var a=createjs.extend(CSSLoader,createjs.AbstractLoader),b=CSSLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.CSS},a._formatResult=function(a){if(this._preferXHR){var b=a.getTag();if(b.styleSheet)b.styleSheet.cssText=a.getResult(!0);else{var c=document.createTextNode(a.getResult(!0));b.appendChild(c)}}else b=this._tag;return createjs.DomUtils.appendToHead(b),b},createjs.CSSLoader=createjs.promote(CSSLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function ImageLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.AbstractLoader.IMAGE),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",createjs.RequestUtils.isImageTag(a)?this._tag=a:createjs.RequestUtils.isImageTag(a.src)?this._tag=a.src:createjs.RequestUtils.isImageTag(a.tag)&&(this._tag=a.tag),null!=this._tag?this._preferXHR=!1:this._tag=document.createElement("img"),this.on("initialize",this._updateXHR,this)}var a=createjs.extend(ImageLoader,createjs.AbstractLoader),b=ImageLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.IMAGE},a.load=function(){if(""!=this._tag.src&&this._tag.complete)return void this._sendComplete();var a=this._item.crossOrigin;1==a&&(a="Anonymous"),null==a||createjs.RequestUtils.isLocal(this._item.src)||(this._tag.crossOrigin=a),this.AbstractLoader_load()},a._updateXHR=function(a){a.loader.mimeType="text/plain; charset=x-user-defined-binary",a.loader.setResponseType&&a.loader.setResponseType("blob")},a._formatResult=function(){return this._formatImage},a._formatImage=function(a,b){var c=this._tag,d=window.URL||window.webkitURL;if(this._preferXHR)if(d){var e=d.createObjectURL(this.getResult(!0));c.src=e,c.addEventListener("load",this._cleanUpURL,!1),c.addEventListener("error",this._cleanUpURL,!1)}else c.src=loader.getItem().src;else;c.complete?a(c):(c.addEventListener("load",createjs.proxy(function(){a(this._tag)},this),!1),c.addEventListener("error",createjs.proxy(function(){b(this._tag)},this),!1))},a._cleanUpURL=function(a){var b=window.URL||window.webkitURL;b.revokeObjectURL(a.target.src)},createjs.ImageLoader=createjs.promote(ImageLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function JavaScriptLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.AbstractLoader.JAVASCRIPT),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.setTag(document.createElement("script"))}var a=createjs.extend(JavaScriptLoader,createjs.AbstractLoader),b=JavaScriptLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.JAVASCRIPT},a._formatResult=function(a){var b=a.getTag();return this._preferXHR&&(b.text=a.getResult(!0)),b},createjs.JavaScriptLoader=createjs.promote(JavaScriptLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function JSONLoader(a){this.AbstractLoader_constructor(a,!0,createjs.AbstractLoader.JSON),this.resultFormatter=this._formatResult}var a=createjs.extend(JSONLoader,createjs.AbstractLoader),b=JSONLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.JSON},a._formatResult=function(a){var b=null;try{b=createjs.DataUtils.parseJSON(a.getResult(!0))}catch(c){var d=new createjs.ErrorEvent("JSON_FORMAT",null,c);return this._sendError(d),c}return b},createjs.JSONLoader=createjs.promote(JSONLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function JSONPLoader(a){this.AbstractLoader_constructor(a,!1,createjs.AbstractLoader.JSONP),this.setTag(document.createElement("script")),this.getTag().type="text/javascript"}var a=createjs.extend(JSONPLoader,createjs.AbstractLoader),b=JSONPLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.JSONP},a.cancel=function(){this.AbstractLoader_cancel(),this._dispose()},a.load=function(){if(null==this._item.callback)throw new Error("callback is required for loading JSONP requests.");if(null!=window[this._item.callback])throw new Error("JSONP callback '"+this._item.callback+"' already exists on window. You need to specify a different callback or re-name the current one.");window[this._item.callback]=createjs.proxy(this._handleLoad,this),window.document.body.appendChild(this._tag),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag.src=this._item.src},a._handleLoad=function(a){this._result=this._rawResult=a,this._sendComplete(),this._dispose()},a._handleTimeout=function(){this._dispose(),this.dispatchEvent(new createjs.ErrorEvent("timeout"))},a._dispose=function(){window.document.body.removeChild(this._tag),delete window[this._item.callback],clearTimeout(this._loadTimeout)},createjs.JSONPLoader=createjs.promote(JSONPLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function ManifestLoader(a){this.AbstractLoader_constructor(a,null,createjs.AbstractLoader.MANIFEST),this.plugins=null,this._manifestQueue=null}var a=createjs.extend(ManifestLoader,createjs.AbstractLoader),b=ManifestLoader;b.MANIFEST_PROGRESS=.25,b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.MANIFEST},a.load=function(){this.AbstractLoader_load()},a._createRequest=function(){var a=this._item.callback;this._request=null!=a?new createjs.JSONPLoader(this._item):new createjs.JSONLoader(this._item)},a.handleEvent=function(a){switch(a.type){case"complete":return this._rawResult=a.target.getResult(!0),this._result=a.target.getResult(),this._sendProgress(b.MANIFEST_PROGRESS),void this._loadManifest(this._result);case"progress":return a.loaded*=b.MANIFEST_PROGRESS,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0),void this._sendProgress(a)}this.AbstractLoader_handleEvent(a)},a.destroy=function(){this.AbstractLoader_destroy(),this._manifestQueue.close()},a._loadManifest=function(a){if(a&&a.manifest){var b=this._manifestQueue=new createjs.LoadQueue;b.on("fileload",this._handleManifestFileLoad,this),b.on("progress",this._handleManifestProgress,this),b.on("complete",this._handleManifestComplete,this,!0),b.on("error",this._handleManifestError,this,!0);for(var c=0,d=this.plugins.length;d>c;c++)b.installPlugin(this.plugins[c]);b.loadManifest(a)}else this._sendComplete()},a._handleManifestFileLoad=function(a){a.target=null,this.dispatchEvent(a)},a._handleManifestComplete=function(){this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},a._handleManifestProgress=function(a){this.progress=a.progress*(1-b.MANIFEST_PROGRESS)+b.MANIFEST_PROGRESS,this._sendProgress(this.progress)},a._handleManifestError=function(a){var b=new createjs.Event("fileerror");b.item=a.data,this.dispatchEvent(b)},createjs.ManifestLoader=createjs.promote(ManifestLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SoundLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.AbstractLoader.SOUND),createjs.RequestUtils.isAudioTag(a)?this._tag=a:createjs.RequestUtils.isAudioTag(a.src)?this._tag=a:createjs.RequestUtils.isAudioTag(a.tag)&&(this._tag=createjs.RequestUtils.isAudioTag(a)?a:a.src),null!=this._tag&&(this._preferXHR=!1)}var a=createjs.extend(SoundLoader,createjs.AbstractMediaLoader),b=SoundLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.SOUND},a._createTag=function(a){var b=document.createElement("audio");return b.autoplay=!1,b.preload="none",b.src=a,b},createjs.SoundLoader=createjs.promote(SoundLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function VideoLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.AbstractLoader.VIDEO),createjs.RequestUtils.isVideoTag(a)||createjs.RequestUtils.isVideoTag(a.src)?(this.setTag(createjs.RequestUtils.isVideoTag(a)?a:a.src),this._preferXHR=!1):this.setTag(this._createTag())}var a=createjs.extend(VideoLoader,createjs.AbstractMediaLoader),b=VideoLoader;a._createTag=function(){return document.createElement("video")},b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.VIDEO},createjs.VideoLoader=createjs.promote(VideoLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SpriteSheetLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.AbstractLoader.SPRITESHEET),this._manifestQueue=null}var a=createjs.extend(SpriteSheetLoader,createjs.AbstractLoader),b=SpriteSheetLoader;b.SPRITESHEET_PROGRESS=.25,b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.SPRITESHEET},a.destroy=function(){this.AbstractLoader_destroy,this._manifestQueue.close()},a._createRequest=function(){var a=this._item.callback;this._request=null!=a?new createjs.JSONPLoader(this._item):new createjs.JSONLoader(this._item)},a.handleEvent=function(a){switch(a.type){case"complete":return this._rawResult=a.target.getResult(!0),this._result=a.target.getResult(),this._sendProgress(b.SPRITESHEET_PROGRESS),void this._loadManifest(this._result);case"progress":return a.loaded*=b.SPRITESHEET_PROGRESS,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0),void this._sendProgress(a)}this.AbstractLoader_handleEvent(a)},a._loadManifest=function(a){if(a&&a.images){var b=this._manifestQueue=new createjs.LoadQueue(this._preferXHR,this._item.path,this._item.crossOrigin);b.on("complete",this._handleManifestComplete,this,!0),b.on("fileload",this._handleManifestFileLoad,this),b.on("progress",this._handleManifestProgress,this),b.on("error",this._handleManifestError,this,!0),b.loadManifest(a.images)}},a._handleManifestFileLoad=function(a){var b=a.result;if(null!=b){var c=this.getResult().images,d=c.indexOf(a.item.src);c[d]=b}},a._handleManifestComplete=function(){this._result=new createjs.SpriteSheet(this._result),this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},a._handleManifestProgress=function(a){this.progress=a.progress*(1-b.SPRITESHEET_PROGRESS)+b.SPRITESHEET_PROGRESS,this._sendProgress(this.progress)},a._handleManifestError=function(a){var b=new createjs.Event("fileerror");b.item=a.data,this.dispatchEvent(b)},createjs.SpriteSheetLoader=createjs.promote(SpriteSheetLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SVGLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.AbstractLoader.SVG),this.resultFormatter=this._formatResult,this._tagSrcAttribute="data",b?this.setTag(document.createElement("svg")):(this.setTag(document.createElement("object")),this.getTag().type="image/svg+xml")}var a=createjs.extend(SVGLoader,createjs.AbstractLoader),b=SVGLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.SVG},a._formatResult=function(a){var b=createjs.DataUtils.parseXML(a.getResult(!0),"text/xml"),c=a.getTag();return!this._preferXHR&&document.body.contains(c)&&document.body.removeChild(c),null!=b.documentElement?(c.appendChild(b.documentElement),c.style.visibility="visible",c):b},createjs.SVGLoader=createjs.promote(SVGLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function XMLLoader(a){this.AbstractLoader_constructor(a,!0,createjs.AbstractLoader.XML),this.resultFormatter=this._formatResult}var a=createjs.extend(XMLLoader,createjs.AbstractLoader),b=XMLLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.XML},a._formatResult=function(a){return createjs.DataUtils.parseXML(a.getResult(!0),"text/xml")},createjs.XMLLoader=createjs.promote(XMLLoader,"AbstractLoader")}();
\ No newline at end of file
+var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";var b=a.PreloadJS=a.PreloadJS||{};b.version="NEXT",b.buildDate="Wed, 02 Dec 2015 18:53:18 GMT"}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},scope.createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c};var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},scope.createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a};var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";a.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},scope.createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1};var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var b=Event.prototype;b.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},b.set=function(a){for(var b in a)this[b]=a[b];return this},b.toString=function(){return"[Event (type="+this.type+")]"},a.Event=Event}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function ErrorEvent(a,b,c){this.Event_constructor("error"),this.title=a,this.message=b,this.data=c}var b=a.extend(ErrorEvent,a.Event);b.clone=function(){return new a.ErrorEvent(this.title,this.message,this.data)},a.ErrorEvent=a.promote(ErrorEvent,"Event")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var b=EventDispatcher.prototype;EventDispatcher.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(b){if("string"==typeof b){var c=this._listeners;if(!c||!c[b])return!1;b=new a.Event(b)}else b.target&&b.clone&&(b=b.clone());try{b.target=this}catch(d){}if(b.bubbles&&this.parent){for(var e=this,f=[e];e.parent;)f.push(e=e.parent);var g,h=f.length;for(g=h-1;g>=0&&!b.propagationStopped;g--)f[g]._dispatchEvent(b,1+(0==g));for(g=1;h>g&&!b.propagationStopped;g++)f[g]._dispatchEvent(b,3)}else this._dispatchEvent(b,2);return b.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;try{a.currentTarget=this}catch(f){}try{a.eventPhase=b}catch(f){}a.removed=!1,e=e.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=e[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}},a.EventDispatcher=EventDispatcher}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function ProgressEvent(a,b){this.Event_constructor("progress"),this.loaded=a,this.total=null==b?1:b,this.progress=0==b?0:this.loaded/this.total}var b=a.extend(ProgressEvent,a.Event);b.clone=function(){return new a.ProgressEvent(this.loaded,this.total)},a.ProgressEvent=a.promote(ProgressEvent,"Event")}(scope.createjs),function(){function a(b,d){function f(a){if(f[a]!==q)return f[a];var b;if("bug-string-char-index"==a)b="a"!="a"[0];else if("json"==a)b=f("json-stringify")&&f("json-parse");else{var c,e='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==a){var i=d.stringify,k="function"==typeof i&&t;if(k){(c=function(){return 1}).toJSON=c;try{k="0"===i(0)&&"0"===i(new g)&&'""'==i(new h)&&i(s)===q&&i(q)===q&&i()===q&&"1"===i(c)&&"[1]"==i([c])&&"[null]"==i([q])&&"null"==i(null)&&"[null,null,null]"==i([q,s,null])&&i({a:[c,!0,!1,null,"\x00\b\n\f\r "]})==e&&"1"===i(null,c)&&"[\n 1,\n 2\n]"==i([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==i(new j(-864e13))&&'"+275760-09-13T00:00:00.000Z"'==i(new j(864e13))&&'"-000001-01-01T00:00:00.000Z"'==i(new j(-621987552e5))&&'"1969-12-31T23:59:59.999Z"'==i(new j(-1))}catch(l){k=!1}}b=k}if("json-parse"==a){var m=d.parse;if("function"==typeof m)try{if(0===m("0")&&!m(!1)){c=m(e);var n=5==c.a.length&&1===c.a[0];if(n){try{n=!m('" "')}catch(l){}if(n)try{n=1!==m("01")}catch(l){}if(n)try{n=1!==m("1.")}catch(l){}}}}catch(l){n=!1}b=n}}return f[a]=!!b}b||(b=e.Object()),d||(d=e.Object());var g=b.Number||e.Number,h=b.String||e.String,i=b.Object||e.Object,j=b.Date||e.Date,k=b.SyntaxError||e.SyntaxError,l=b.TypeError||e.TypeError,m=b.Math||e.Math,n=b.JSON||e.JSON;"object"==typeof n&&n&&(d.stringify=n.stringify,d.parse=n.parse);var o,p,q,r=i.prototype,s=r.toString,t=new j(-0xc782b5b800cec);try{t=-109252==t.getUTCFullYear()&&0===t.getUTCMonth()&&1===t.getUTCDate()&&10==t.getUTCHours()&&37==t.getUTCMinutes()&&6==t.getUTCSeconds()&&708==t.getUTCMilliseconds()}catch(u){}if(!f("json")){var v="[object Function]",w="[object Date]",x="[object Number]",y="[object String]",z="[object Array]",A="[object Boolean]",B=f("bug-string-char-index");if(!t)var C=m.floor,D=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,b){return D[b]+365*(a-1970)+C((a-1969+(b=+(b>1)))/4)-C((a-1901+b)/100)+C((a-1601+b)/400)};if((o=r.hasOwnProperty)||(o=function(a){var b,c={};return(c.__proto__=null,c.__proto__={toString:1},c).toString!=s?o=function(a){var b=this.__proto__,c=a in(this.__proto__=null,this);return this.__proto__=b,c}:(b=c.constructor,o=function(a){var c=(this.constructor||b).prototype;return a in this&&!(a in c&&this[a]===c[a])}),c=null,o.call(this,a)}),p=function(a,b){var d,e,f,g=0;(d=function(){this.valueOf=0}).prototype.valueOf=0,e=new d;for(f in e)o.call(e,f)&&g++;return d=e=null,g?p=2==g?function(a,b){var c,d={},e=s.call(a)==v;for(c in a)e&&"prototype"==c||o.call(d,c)||!(d[c]=1)||!o.call(a,c)||b(c)}:function(a,b){var c,d,e=s.call(a)==v;for(c in a)e&&"prototype"==c||!o.call(a,c)||(d="constructor"===c)||b(c);(d||o.call(a,c="constructor"))&&b(c)}:(e=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],p=function(a,b){var d,f,g=s.call(a)==v,h=!g&&"function"!=typeof a.constructor&&c[typeof a.hasOwnProperty]&&a.hasOwnProperty||o;for(d in a)g&&"prototype"==d||!h.call(a,d)||b(d);for(f=e.length;d=e[--f];h.call(a,d)&&b(d));}),p(a,b)},!f("json-stringify")){var F={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},G="000000",H=function(a,b){return(G+(b||0)).slice(-a)},I="\\u00",J=function(a){for(var b='"',c=0,d=a.length,e=!B||d>10,f=e&&(B?a.split(""):a);d>c;c++){var g=a.charCodeAt(c);switch(g){case 8:case 9:case 10:case 12:case 13:case 34:case 92:b+=F[g];break;default:if(32>g){b+=I+H(2,g.toString(16));break}b+=e?f[c]:a.charAt(c)}}return b+'"'},K=function(a,b,c,d,e,f,g){var h,i,j,k,m,n,r,t,u,v,B,D,F,G,I,L;try{h=b[a]}catch(M){}if("object"==typeof h&&h)if(i=s.call(h),i!=w||o.call(h,"toJSON"))"function"==typeof h.toJSON&&(i!=x&&i!=y&&i!=z||o.call(h,"toJSON"))&&(h=h.toJSON(a));else if(h>-1/0&&1/0>h){if(E){for(m=C(h/864e5),j=C(m/365.2425)+1970-1;E(j+1,0)<=m;j++);for(k=C((m-E(j,0))/30.42);E(j,k+1)<=m;k++);m=1+m-E(j,k),n=(h%864e5+864e5)%864e5,r=C(n/36e5)%24,t=C(n/6e4)%60,u=C(n/1e3)%60,v=n%1e3}else j=h.getUTCFullYear(),k=h.getUTCMonth(),m=h.getUTCDate(),r=h.getUTCHours(),t=h.getUTCMinutes(),u=h.getUTCSeconds(),v=h.getUTCMilliseconds();h=(0>=j||j>=1e4?(0>j?"-":"+")+H(6,0>j?-j:j):H(4,j))+"-"+H(2,k+1)+"-"+H(2,m)+"T"+H(2,r)+":"+H(2,t)+":"+H(2,u)+"."+H(3,v)+"Z"}else h=null;if(c&&(h=c.call(b,a,h)),null===h)return"null";if(i=s.call(h),i==A)return""+h;if(i==x)return h>-1/0&&1/0>h?""+h:"null";if(i==y)return J(""+h);if("object"==typeof h){for(G=g.length;G--;)if(g[G]===h)throw l();if(g.push(h),B=[],I=f,f+=e,i==z){for(F=0,G=h.length;G>F;F++)D=K(F,h,c,d,e,f,g),B.push(D===q?"null":D);L=B.length?e?"[\n"+f+B.join(",\n"+f)+"\n"+I+"]":"["+B.join(",")+"]":"[]"}else p(d||h,function(a){var b=K(a,h,c,d,e,f,g);b!==q&&B.push(J(a)+":"+(e?" ":"")+b)}),L=B.length?e?"{\n"+f+B.join(",\n"+f)+"\n"+I+"}":"{"+B.join(",")+"}":"{}";return g.pop(),L}};d.stringify=function(a,b,d){var e,f,g,h;if(c[typeof b]&&b)if((h=s.call(b))==v)f=b;else if(h==z){g={};for(var i,j=0,k=b.length;k>j;i=b[j++],h=s.call(i),(h==y||h==x)&&(g[i]=1));}if(d)if((h=s.call(d))==x){if((d-=d%1)>0)for(e="",d>10&&(d=10);e.lengthL;)switch(e=f.charCodeAt(L)){case 9:case 10:case 13:case 32:L++;break;case 123:case 125:case 91:case 93:case 58:case 44:return a=B?f.charAt(L):f[L],L++,a;case 34:for(a="@",L++;g>L;)if(e=f.charCodeAt(L),32>e)P();else if(92==e)switch(e=f.charCodeAt(++L)){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:a+=O[e],L++;break;case 117:for(b=++L,c=L+4;c>L;L++)e=f.charCodeAt(L),e>=48&&57>=e||e>=97&&102>=e||e>=65&&70>=e||P();a+=N("0x"+f.slice(b,L));break;default:P()}else{if(34==e)break;for(e=f.charCodeAt(L),b=L;e>=32&&92!=e&&34!=e;)e=f.charCodeAt(++L);a+=f.slice(b,L)}if(34==f.charCodeAt(L))return L++,a;P();default:if(b=L,45==e&&(d=!0,e=f.charCodeAt(++L)),e>=48&&57>=e){for(48==e&&(e=f.charCodeAt(L+1),e>=48&&57>=e)&&P(),d=!1;g>L&&(e=f.charCodeAt(L),e>=48&&57>=e);L++);if(46==f.charCodeAt(L)){for(c=++L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}if(e=f.charCodeAt(L),101==e||69==e){for(e=f.charCodeAt(++L),(43==e||45==e)&&L++,c=L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}return+f.slice(b,L)}if(d&&P(),"true"==f.slice(L,L+4))return L+=4,!0;if("false"==f.slice(L,L+5))return L+=5,!1;if("null"==f.slice(L,L+4))return L+=4,null;P()}return"$"},R=function(a){var b,c;if("$"==a&&P(),"string"==typeof a){if("@"==(B?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(b=[];a=Q(),"]"!=a;c||(c=!0))c&&(","==a?(a=Q(),"]"==a&&P()):P()),","==a&&P(),b.push(R(a));return b}if("{"==a){for(b={};a=Q(),"}"!=a;c||(c=!0))c&&(","==a?(a=Q(),"}"==a&&P()):P()),(","==a||"string"!=typeof a||"@"!=(B?a.charAt(0):a[0])||":"!=Q())&&P(),b[a.slice(1)]=R(Q());return b}P()}return a},S=function(a,b,c){var d=T(a,b,c);d===q?delete a[b]:a[b]=d},T=function(a,b,c){var d,e=a[b];if("object"==typeof e&&e)if(s.call(e)==z)for(d=e.length;d--;)S(e,d,c);else p(e,function(a){S(e,a,c)});return c.call(a,b,e)};d.parse=function(a,b){var c,d;return L=0,M=""+a,c=R(Q()),"$"!=Q()&&P(),L=M=null,b&&s.call(b)==v?T((d={},d[""]=c,d),"",b):c}}}return d.runInContext=a,d}var b="function"==typeof define&&define.amd,c={"function":!0,object:!0},d=c[typeof exports]&&exports&&!exports.nodeType&&exports,e=c[typeof window]&&window||this,f=d&&c[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;if(!f||f.global!==f&&f.window!==f&&f.self!==f||(e=f),d&&!b)a(e,d);else{var g=e.JSON,h=e.JSON3,i=!1,j=a(e,e.JSON3={noConflict:function(){return i||(i=!0,e.JSON=g,e.JSON3=h,g=h=null),j}});e.JSON={parse:j.parse,stringify:j.stringify}}b&&define(function(){return j})}.call(this);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){var b={};b.appendToHead=function(a){b.getHead().appendChild(a)},b.getHead=function(){return document.head||document.getElementsByTagName("head")[0]},b.getBody=function(){return document.body||document.getElementsByTagName("body")[0]},a.DomUtils=b}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){var b={};b.parseXML=function(a,b){var c=null;try{if(window.DOMParser){var d=new DOMParser;c=d.parseFromString(a,b)}}catch(e){}if(!c)try{c=new ActiveXObject("Microsoft.XMLDOM"),c.async=!1,c.loadXML(a)}catch(e){c=null}return c},b.parseJSON=function(a){if(null==a)return null;try{return JSON.parse(a)}catch(b){throw b}},a.DataUtils=b}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function LoadItem(){this.src=null,this.type=null,this.id=null,this.maintainOrder=!1,this.callback=null,this.data=null,this.method=a.LoadItem.GET,this.values=null,this.headers=null,this.withCredentials=!1,this.mimeType=null,this.crossOrigin=null,this.loadTimeout=c.LOAD_TIMEOUT_DEFAULT}var b=LoadItem.prototype={},c=LoadItem;c.LOAD_TIMEOUT_DEFAULT=8e3,c.create=function(a){if("string"==typeof a){var b=new LoadItem;return b.src=a,b}if(a instanceof c)return a;if(a instanceof Object&&a.src)return null==a.loadTimeout&&(a.loadTimeout=c.LOAD_TIMEOUT_DEFAULT),a;throw new Error("Type not recognized.")},b.set=function(a){for(var b in a)this[b]=a[b];return this},a.LoadItem=c}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){var b={};b.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,b.RELATIVE_PATT=/^[.\/]*?\//i,b.EXTENSION_PATT=/\/?[^\/]+\.(\w{1,5})$/i,b.parseURI=function(a){var c={absolute:!1,relative:!1};if(null==a)return c;var d=a.indexOf("?");d>-1&&(a=a.substr(0,d));var e;return b.ABSOLUTE_PATT.test(a)?c.absolute=!0:b.RELATIVE_PATT.test(a)&&(c.relative=!0),(e=a.match(b.EXTENSION_PATT))&&(c.extension=e[1].toLowerCase()),c},b.formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},b.buildPath=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this._formatQueryString(b,c):a+"?"+this._formatQueryString(b,c)},b.isCrossDomain=function(a){var b=document.createElement("a");b.href=a.src;var c=document.createElement("a");c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},b.isLocal=function(a){var b=document.createElement("a");return b.href=a.src,""==b.hostname&&"file:"==b.protocol},b.isBinary=function(b){switch(b){case a.AbstractLoader.IMAGE:case a.AbstractLoader.BINARY:return!0;default:return!1}},b.isImageTag=function(a){return a instanceof HTMLImageElement},b.isAudioTag=function(a){return window.HTMLAudioElement?a instanceof HTMLAudioElement:!1},b.isVideoTag=function(a){return window.HTMLVideoElement?a instanceof HTMLVideoElement:!1},b.isText=function(b){switch(b){case a.AbstractLoader.TEXT:case a.AbstractLoader.JSON:case a.AbstractLoader.MANIFEST:case a.AbstractLoader.XML:case a.AbstractLoader.CSS:case a.AbstractLoader.SVG:case a.AbstractLoader.JAVASCRIPT:case a.AbstractLoader.SPRITESHEET:return!0;default:return!1}},b.getTypeByExtension=function(b){if(null==b)return a.AbstractLoader.TEXT;switch(b.toLowerCase()){case"jpeg":case"jpg":case"gif":case"png":case"webp":case"bmp":return a.AbstractLoader.IMAGE;case"ogg":case"mp3":case"webm":return a.AbstractLoader.SOUND;case"mp4":case"webm":case"ts":return a.AbstractLoader.VIDEO;case"json":return a.AbstractLoader.JSON;case"xml":return a.AbstractLoader.XML;case"css":return a.AbstractLoader.CSS;case"js":return a.AbstractLoader.JAVASCRIPT;case"svg":return a.AbstractLoader.SVG;default:return a.AbstractLoader.TEXT}},a.RequestUtils=b}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function AbstractLoader(b,c,d){this.EventDispatcher_constructor(),this.loaded=!1,this.canceled=!1,this.progress=0,this.type=d,this.resultFormatter=null,this._item=b?a.LoadItem.create(b):null,this._preferXHR=c,this._result=null,this._rawResult=null,this._loadedItems=null,this._tagSrcAttribute=null,this._tag=null}var b=a.extend(AbstractLoader,a.EventDispatcher),c=AbstractLoader;c.POST="POST",c.GET="GET",c.BINARY="binary",c.CSS="css",c.IMAGE="image",c.JAVASCRIPT="javascript",c.JSON="json",c.JSONP="jsonp",c.MANIFEST="manifest",c.SOUND="sound",c.VIDEO="video",c.SPRITESHEET="spritesheet",c.SVG="svg",c.TEXT="text",c.XML="xml",b.getItem=function(){return this._item},b.getResult=function(a){return a?this._rawResult:this._result},b.getTag=function(){return this._tag},b.setTag=function(a){this._tag=a},b.load=function(){this._createRequest(),this._request.on("complete",this,this),this._request.on("progress",this,this),this._request.on("loadStart",this,this),this._request.on("abort",this,this),this._request.on("timeout",this,this),this._request.on("error",this,this);var b=new a.Event("initialize");b.loader=this._request,this.dispatchEvent(b),this._request.load()},b.cancel=function(){this.canceled=!0,this.destroy()},b.destroy=function(){this._request&&(this._request.removeAllEventListeners(),this._request.destroy()),this._request=null,this._item=null,this._rawResult=null,this._result=null,this._loadItems=null,this.removeAllEventListeners()},b.getLoadedItems=function(){return this._loadedItems},b._createRequest=function(){this._request=this._preferXHR?new a.XHRRequest(this._item):new a.TagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},b._createTag=function(){return null},b._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},b._sendProgress=function(b){if(!this._isCanceled()){var c=null;"number"==typeof b?(this.progress=b,c=new a.ProgressEvent(this.progress)):(c=b,this.progress=b.loaded/b.total,c.progress=this.progress,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),this.hasEventListener("progress")&&this.dispatchEvent(c)}},b._sendComplete=function(){if(!this._isCanceled()){this.loaded=!0;var b=new a.Event("complete");b.rawResult=this._rawResult,null!=this._result&&(b.result=this._result),this.dispatchEvent(b)}},b._sendError=function(b){!this._isCanceled()&&this.hasEventListener("error")&&(null==b&&(b=new a.ErrorEvent("PRELOAD_ERROR_EMPTY")),this.dispatchEvent(b))},b._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},b.resultFormatter=null,b.handleEvent=function(b){switch(b.type){case"complete":this._rawResult=b.target._response;var c=this.resultFormatter&&this.resultFormatter(this);c instanceof Function?c.call(this,a.proxy(this._resultFormatSuccess,this),a.proxy(this._resultFormatFailed,this)):(this._result=c||this._rawResult,this._sendComplete());break;case"progress":this._sendProgress(b);break;case"error":this._sendError(b);break;case"loadstart":this._sendLoadStart();break;case"abort":case"timeout":this._isCanceled()||this.dispatchEvent(new a.ErrorEvent("PRELOAD_"+b.type.toUpperCase()+"_ERROR"))}},b._resultFormatSuccess=function(a){this._result=a,this._sendComplete()},b._resultFormatFailed=function(a){this._sendError(a)},b.buildPath=function(b,c){return a.RequestUtils.buildPath(b,c)},b.toString=function(){return"[PreloadJS AbstractLoader]"},a.AbstractLoader=a.promote(AbstractLoader,"EventDispatcher")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function AbstractMediaLoader(a,b,c){this.AbstractLoader_constructor(a,b,c),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.on("initialize",this._updateXHR,this)}var b=a.extend(AbstractMediaLoader,a.AbstractLoader);b.load=function(){this._tag||(this._tag=this._createTag(this._item.src)),this._tag.preload="auto",this._tag.load(),this.AbstractLoader_load()},b._createTag=function(){},b._createRequest=function(){this._request=this._preferXHR?new a.XHRRequest(this._item):new a.MediaTagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},b._updateXHR=function(a){a.loader.setResponseType&&a.loader.setResponseType("blob")},b._formatResult=function(a){if(this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.onstalled=null,this._preferXHR){var b=window.URL||window.webkitURL,c=a.getResult(!0);a.getTag().src=b.createObjectURL(c)}return a.getTag()},a.AbstractMediaLoader=a.promote(AbstractMediaLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";var AbstractRequest=function(a){this._item=a},b=a.extend(AbstractRequest,a.EventDispatcher);b.load=function(){},b.destroy=function(){},b.cancel=function(){},a.AbstractRequest=a.promote(AbstractRequest,"EventDispatcher")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function TagRequest(b,c,d){this.AbstractRequest_constructor(b),this._tag=c,this._tagSrcAttribute=d,this._loadedHandler=a.proxy(this._handleTagComplete,this),this._addedToDOM=!1,this._startTagVisibility=null}var b=a.extend(TagRequest,a.AbstractRequest);b.load=function(){this._tag.onload=a.proxy(this._handleTagComplete,this),this._tag.onreadystatechange=a.proxy(this._handleReadyStateChange,this),this._tag.onerror=a.proxy(this._handleError,this);var b=new a.Event("initialize");b.loader=this._tag,this.dispatchEvent(b),this._hideTag(),this._loadTimeout=setTimeout(a.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag[this._tagSrcAttribute]=this._item.src,null==this._tag.parentNode&&(window.document.body.appendChild(this._tag),this._addedToDOM=!0)},b.destroy=function(){this._clean(),this._tag=null,this.AbstractRequest_destroy()},b._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},b._handleError=function(){this._clean(),this.dispatchEvent("error")},b._handleTagComplete=function(){this._rawResult=this._tag,this._result=this.resultFormatter&&this.resultFormatter(this)||this._rawResult,this._clean(),this._showTag(),this.dispatchEvent("complete")},b._handleTimeout=function(){this._clean(),this.dispatchEvent(new a.Event("timeout"))},b._clean=function(){this._tag.onload=null,this._tag.onreadystatechange=null,this._tag.onerror=null,this._addedToDOM&&null!=this._tag.parentNode&&this._tag.parentNode.removeChild(this._tag),clearTimeout(this._loadTimeout)},b._hideTag=function(){this._startTagVisibility=this._tag.style.visibility,this._tag.style.visibility="hidden"},b._showTag=function(){this._tag.style.visibility=this._startTagVisibility},b._handleStalled=function(){},a.TagRequest=a.promote(TagRequest,"AbstractRequest")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function MediaTagRequest(b,c,d){this.AbstractRequest_constructor(b),this._tag=c,this._tagSrcAttribute=d,this._loadedHandler=a.proxy(this._handleTagComplete,this)}var b=a.extend(MediaTagRequest,a.TagRequest);b.load=function(){var b=a.proxy(this._handleStalled,this);this._stalledCallback=b;var c=a.proxy(this._handleProgress,this);this._handleProgress=c,this._tag.addEventListener("stalled",b),this._tag.addEventListener("progress",c),this._tag.addEventListener&&this._tag.addEventListener("canplaythrough",this._loadedHandler,!1),this.TagRequest_load()},b._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},b._handleStalled=function(){},b._handleProgress=function(b){if(b&&!(b.loaded>0&&0==b.total)){var c=new a.ProgressEvent(b.loaded,b.total);this.dispatchEvent(c)}},b._clean=function(){this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.removeEventListener("stalled",this._stalledCallback),this._tag.removeEventListener("progress",this._progressCallback),this.TagRequest__clean()},a.MediaTagRequest=a.promote(MediaTagRequest,"TagRequest")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function XHRRequest(b){this.AbstractRequest_constructor(b),this._request=null,this._loadTimeout=null,this._xhrLevel=1,this._response=null,this._rawResponse=null,this._canceled=!1,this._handleLoadStartProxy=a.proxy(this._handleLoadStart,this),this._handleProgressProxy=a.proxy(this._handleProgress,this),this._handleAbortProxy=a.proxy(this._handleAbort,this),this._handleErrorProxy=a.proxy(this._handleError,this),this._handleTimeoutProxy=a.proxy(this._handleTimeout,this),this._handleLoadProxy=a.proxy(this._handleLoad,this),this._handleReadyStateChangeProxy=a.proxy(this._handleReadyStateChange,this),!this._createXHR(b)}var b=a.extend(XHRRequest,a.AbstractRequest);XHRRequest.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],b.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},b.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},b.load=function(){if(null==this._request)return void this._handleError();null!=this._request.addEventListener?(this._request.addEventListener("loadstart",this._handleLoadStartProxy,!1),this._request.addEventListener("progress",this._handleProgressProxy,!1),this._request.addEventListener("abort",this._handleAbortProxy,!1),this._request.addEventListener("error",this._handleErrorProxy,!1),this._request.addEventListener("timeout",this._handleTimeoutProxy,!1),this._request.addEventListener("load",this._handleLoadProxy,!1),this._request.addEventListener("readystatechange",this._handleReadyStateChangeProxy,!1)):(this._request.onloadstart=this._handleLoadStartProxy,this._request.onprogress=this._handleProgressProxy,this._request.onabort=this._handleAbortProxy,this._request.onerror=this._handleErrorProxy,this._request.ontimeout=this._handleTimeoutProxy,this._request.onload=this._handleLoadProxy,this._request.onreadystatechange=this._handleReadyStateChangeProxy),1==this._xhrLevel&&(this._loadTimeout=setTimeout(a.proxy(this._handleTimeout,this),this._item.loadTimeout));try{this._item.values&&this._item.method!=a.AbstractLoader.GET?this._item.method==a.AbstractLoader.POST&&this._request.send(a.RequestUtils.formatQueryString(this._item.values)):this._request.send()}catch(b){this.dispatchEvent(new a.ErrorEvent("XHR_SEND",null,b))}},b.setResponseType=function(a){"blob"===a&&(a=window.URL?"blob":"arraybuffer",this._responseType=a),this._request.responseType=a},b.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},b.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},b._handleProgress=function(b){if(b&&!(b.loaded>0&&0==b.total)){var c=new a.ProgressEvent(b.loaded,b.total);this.dispatchEvent(c)}},b._handleLoadStart=function(){clearTimeout(this._loadTimeout),this.dispatchEvent("loadstart")},b._handleAbort=function(b){this._clean(),this.dispatchEvent(new a.ErrorEvent("XHR_ABORTED",null,b))},b._handleError=function(b){this._clean(),this.dispatchEvent(new a.ErrorEvent(b.message))},b._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},b._handleLoad=function(){if(!this.loaded){this.loaded=!0;var b=this._checkError();if(b)return void this._handleError(b);if(this._response=this._getResponse(),"arraybuffer"===this._responseType)try{this._response=new Blob([this._response])}catch(c){if(window.BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,"TypeError"===c.name&&window.BlobBuilder){var d=new BlobBuilder;d.append(this._response),this._response=d.getBlob()}}this._clean(),this.dispatchEvent(new a.Event("complete"))}},b._handleTimeout=function(b){this._clean(),this.dispatchEvent(new a.ErrorEvent("PRELOAD_TIMEOUT",null,b))},b._checkError=function(){var a=parseInt(this._request.status);switch(a){case 404:case 0:return new Error(a)}return null},b._getResponse=function(){if(null!=this._response)return this._response;if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},b._createXHR=function(b){var c=a.RequestUtils.isCrossDomain(b),d={},e=null;if(window.XMLHttpRequest)e=new XMLHttpRequest,c&&void 0===e.withCredentials&&window.XDomainRequest&&(e=new XDomainRequest);else{for(var f=0,g=s.ACTIVEX_VERSIONS.length;g>f;f++){var h=s.ACTIVEX_VERSIONS[f];try{e=new ActiveXObject(h);break}catch(i){}}if(null==e)return!1}null==b.mimeType&&a.RequestUtils.isText(b.type)&&(b.mimeType="text/plain; charset=utf-8"),b.mimeType&&e.overrideMimeType&&e.overrideMimeType(b.mimeType),this._xhrLevel="string"==typeof e.responseType?2:1;var j=null;if(j=b.method==a.AbstractLoader.GET?a.RequestUtils.buildPath(b.src,b.values):b.src,e.open(b.method||a.AbstractLoader.GET,j,!0),c&&e instanceof XMLHttpRequest&&1==this._xhrLevel&&(d.Origin=location.origin),b.values&&b.method==a.AbstractLoader.POST&&(d["Content-Type"]="application/x-www-form-urlencoded"),c||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest"),b.headers)for(var k in b.headers)d[k]=b.headers[k];for(k in d)e.setRequestHeader(k,d[k]);return e instanceof XMLHttpRequest&&void 0!==b.withCredentials&&(e.withCredentials=b.withCredentials),this._request=e,!0},b._clean=function(){clearTimeout(this._loadTimeout),null!=this._request.removeEventListener?(this._request.removeEventListener("loadstart",this._handleLoadStartProxy),this._request.removeEventListener("progress",this._handleProgressProxy),this._request.removeEventListener("abort",this._handleAbortProxy),this._request.removeEventListener("error",this._handleErrorProxy),this._request.removeEventListener("timeout",this._handleTimeoutProxy),this._request.removeEventListener("load",this._handleLoadProxy),this._request.removeEventListener("readystatechange",this._handleReadyStateChangeProxy)):(this._request.onloadstart=null,this._request.onprogress=null,this._request.onabort=null,this._request.onerror=null,this._request.ontimeout=null,this._request.onload=null,this._request.onreadystatechange=null)},b.toString=function(){return"[PreloadJS XHRRequest]"
+},a.XHRRequest=a.promote(XHRRequest,"AbstractRequest")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function LoadQueue(b,c,d){this.AbstractLoader_constructor(),this._plugins=[],this._typeCallbacks={},this._extensionCallbacks={},this.next=null,this.maintainScriptOrder=!0,this.stopOnError=!1,this._maxConnections=1,this._availableLoaders=[a.ImageLoader,a.JavaScriptLoader,a.CSSLoader,a.JSONLoader,a.JSONPLoader,a.SoundLoader,a.ManifestLoader,a.SpriteSheetLoader,a.XMLLoader,a.SVGLoader,a.BinaryLoader,a.VideoLoader,a.TextLoader],this._defaultLoaderLength=this._availableLoaders.length,this.init(b,c,d)}var b=a.extend(LoadQueue,a.AbstractLoader),c=LoadQueue;b.init=function(a,b,c){this.useXHR=!0,this.preferXHR=!0,this._preferXHR=!0,this.setPreferXHR(a),this._paused=!1,this._basePath=b,this._crossOrigin=c,this._loadStartWasDispatched=!1,this._currentlyLoadingScript=null,this._currentLoads=[],this._loadQueue=[],this._loadQueueBackup=[],this._loadItemsById={},this._loadItemsBySrc={},this._loadedResults={},this._loadedRawResults={},this._numItems=0,this._numItemsLoaded=0,this._scriptOrder=[],this._loadedScripts=[],this._lastProgress=0/0},c.loadTimeout=8e3,c.LOAD_TIMEOUT=0,c.BINARY=a.AbstractLoader.BINARY,c.CSS=a.AbstractLoader.CSS,c.IMAGE=a.AbstractLoader.IMAGE,c.JAVASCRIPT=a.AbstractLoader.JAVASCRIPT,c.JSON=a.AbstractLoader.JSON,c.JSONP=a.AbstractLoader.JSONP,c.MANIFEST=a.AbstractLoader.MANIFEST,c.SOUND=a.AbstractLoader.SOUND,c.VIDEO=a.AbstractLoader.VIDEO,c.SVG=a.AbstractLoader.SVG,c.TEXT=a.AbstractLoader.TEXT,c.XML=a.AbstractLoader.XML,c.POST=a.AbstractLoader.POST,c.GET=a.AbstractLoader.GET,b.registerLoader=function(a){if(!a||!a.canLoadItem)throw new Error("loader is of an incorrect type.");if(-1!=this._availableLoaders.indexOf(a))throw new Error("loader already exists.");this._availableLoaders.unshift(a)},b.unregisterLoader=function(a){var b=this._availableLoaders.indexOf(a);-1!=b&&b0)return;var c=!1;if(b){for(;b.length;){var d=b.pop(),e=this.getResult(d);for(f=this._loadQueue.length-1;f>=0;f--)if(g=this._loadQueue[f].getItem(),g.id==d||g.src==d){this._loadQueue.splice(f,1)[0].cancel();break}for(f=this._loadQueueBackup.length-1;f>=0;f--)if(g=this._loadQueueBackup[f].getItem(),g.id==d||g.src==d){this._loadQueueBackup.splice(f,1)[0].cancel();break}if(e)this._disposeItem(this.getItem(d));else for(var f=this._currentLoads.length-1;f>=0;f--){var g=this._currentLoads[f].getItem();if(g.id==d||g.src==d){this._currentLoads.splice(f,1)[0].cancel(),c=!0;break}}}c&&this._loadNext()}else{this.close();for(var h in this._loadItemsById)this._disposeItem(this._loadItemsById[h]);this.init(this.preferXHR,this._basePath)}},b.reset=function(){this.close();for(var a in this._loadItemsById)this._disposeItem(this._loadItemsById[a]);for(var b=[],c=0,d=this._loadQueueBackup.length;d>c;c++)b.push(this._loadQueueBackup[c].getItem());this.loadManifest(b,!1)},b.installPlugin=function(a){if(null!=a&&null!=a.getPreloadHandlers){this._plugins.push(a);var b=a.getPreloadHandlers();if(b.scope=a,null!=b.types)for(var c=0,d=b.types.length;d>c;c++)this._typeCallbacks[b.types[c]]=b;if(null!=b.extensions)for(c=0,d=b.extensions.length;d>c;c++)this._extensionCallbacks[b.extensions[c]]=b}},b.setMaxConnections=function(a){this._maxConnections=a,!this._paused&&this._loadQueue.length>0&&this._loadNext()},b.loadFile=function(b,c,d){if(null==b){var e=new a.ErrorEvent("PRELOAD_NO_FILE");return void this._sendError(e)}this._addItem(b,null,d),this.setPaused(c!==!1?!1:!0)},b.loadManifest=function(b,d,e){var f=null,g=null;if(Array.isArray(b)){if(0==b.length){var h=new a.ErrorEvent("PRELOAD_MANIFEST_EMPTY");return void this._sendError(h)}f=b}else if("string"==typeof b)f=[{src:b,type:c.MANIFEST}];else{if("object"!=typeof b){var h=new a.ErrorEvent("PRELOAD_MANIFEST_NULL");return void this._sendError(h)}if(void 0!==b.src){if(null==b.type)b.type=c.MANIFEST;else if(b.type!=c.MANIFEST){var h=new a.ErrorEvent("PRELOAD_MANIFEST_TYPE");this._sendError(h)}f=[b]}else void 0!==b.manifest&&(f=b.manifest,g=b.path)}for(var i=0,j=f.length;j>i;i++)this._addItem(f[i],g,e);this.setPaused(d!==!1?!1:!0)},b.load=function(){this.setPaused(!1)},b.getItem=function(a){return this._loadItemsById[a]||this._loadItemsBySrc[a]},b.getResult=function(a,b){var c=this._loadItemsById[a]||this._loadItemsBySrc[a];if(null==c)return null;var d=c.id;return b&&this._loadedRawResults[d]?this._loadedRawResults[d]:this._loadedResults[d]},b.getItems=function(a){var b=[];for(var c in this._loadItemsById){var d=this._loadItemsById[c],e=this.getResult(c);(a!==!0||null!=e)&&b.push({item:d,result:e,rawResult:this.getResult(c,!0)})}return b},b.setPaused=function(a){this._paused=a,this._paused||this._loadNext()},b.close=function(){for(;this._currentLoads.length;)this._currentLoads.pop().cancel();this._scriptOrder.length=0,this._loadedScripts.length=0,this.loadStartWasDispatched=!1,this._itemCount=0,this._lastProgress=0/0},b._addItem=function(b,c,d){var e=this._createLoadItem(b,c,d);if(null!=e){var f=this._createLoader(e);null!=f&&("plugins"in f&&(f.plugins=this._plugins),e._loader=f,this._loadQueue.push(f),this._loadQueueBackup.push(f),this._numItems++,this._updateProgress(),(this.maintainScriptOrder&&e.type==a.LoadQueue.JAVASCRIPT||e.maintainOrder===!0)&&(this._scriptOrder.push(e),this._loadedScripts.push(null)))}},b._createLoadItem=function(b,c,d){var e=a.LoadItem.create(b);if(null==e)return null;var f="",g=d||this._basePath;if(e.src instanceof Object){if(!e.type)return null;if(c){f=c;var h=a.RequestUtils.parseURI(c);null==g||h.absolute||h.relative||(f=g+f)}else null!=g&&(f=g)}else{var i=a.RequestUtils.parseURI(e.src);i.extension&&(e.ext=i.extension),null==e.type&&(e.type=a.RequestUtils.getTypeByExtension(e.ext));var j=e.src;if(!i.absolute&&!i.relative)if(c){f=c;var h=a.RequestUtils.parseURI(c);j=c+j,null==g||h.absolute||h.relative||(f=g+f)}else null!=g&&(f=g);e.src=f+e.src}e.path=f,(void 0===e.id||null===e.id||""===e.id)&&(e.id=j);var k=this._typeCallbacks[e.type]||this._extensionCallbacks[e.ext];if(k){var l=k.callback.call(k.scope,e,this);if(l===!1)return null;l===!0||null!=l&&(e._loader=l),i=a.RequestUtils.parseURI(e.src),null!=i.extension&&(e.ext=i.extension)}return this._loadItemsById[e.id]=e,this._loadItemsBySrc[e.src]=e,null==e.crossOrigin&&(e.crossOrigin=this._crossOrigin),e},b._createLoader=function(a){if(null!=a._loader)return a._loader;for(var b=this.preferXHR,c=0;c=this._maxConnections);a++){var b=this._loadQueue[a];this._canStartLoad(b)&&(this._loadQueue.splice(a,1),a--,this._loadItem(b))}}},b._loadItem=function(a){a.on("fileload",this._handleFileLoad,this),a.on("progress",this._handleProgress,this),a.on("complete",this._handleFileComplete,this),a.on("error",this._handleError,this),a.on("fileerror",this._handleFileError,this),this._currentLoads.push(a),this._sendFileStart(a.getItem()),a.load()},b._handleFileLoad=function(a){a.target=null,this.dispatchEvent(a)},b._handleFileError=function(b){var c=new a.ErrorEvent("FILE_LOAD_ERROR",null,b.item);this._sendError(c)},b._handleError=function(b){var c=b.target;this._numItemsLoaded++,this._finishOrderedItem(c,!0),this._updateProgress();var d=new a.ErrorEvent("FILE_LOAD_ERROR",null,c.getItem());this._sendError(d),this.stopOnError?this.setPaused(!0):(this._removeLoadItem(c),this._cleanLoadItem(c),this._loadNext())},b._handleFileComplete=function(a){var b=a.target,c=b.getItem(),d=b.getResult();this._loadedResults[c.id]=d;var e=b.getResult(!0);null!=e&&e!==d&&(this._loadedRawResults[c.id]=e),this._saveLoadedItems(b),this._removeLoadItem(b),this._finishOrderedItem(b)||this._processFinishedLoad(c,b),this._cleanLoadItem(b)},b._saveLoadedItems=function(a){var b=a.getLoadedItems();if(null!==b)for(var c=0;cc;c++){var d=this._loadedScripts[c];if(null===d)break;if(d!==!0){var e=this._loadedResults[d.id];d.type==a.LoadQueue.JAVASCRIPT&&a.DomUtils.appendToHead(e);var f=d._loader;this._processFinishedLoad(d,f),this._loadedScripts[c]=!0}}},b._processFinishedLoad=function(b,c){if(this._numItemsLoaded++,!this.maintainScriptOrder&&b.type==a.LoadQueue.JAVASCRIPT){var d=c.getTag();a.DomUtils.appendToHead(d)}this._updateProgress(),this._sendFileComplete(b,c),this._loadNext()},b._canStartLoad=function(b){if(!this.maintainScriptOrder||b.preferXHR)return!0;var c=b.getItem();if(c.type!=a.LoadQueue.JAVASCRIPT)return!0;if(this._currentlyLoadingScript)return!1;for(var d=this._scriptOrder.indexOf(c),e=0;d>e;){var f=this._loadedScripts[e];if(null==f)return!1;e++}return this._currentlyLoadingScript=!0,!0},b._removeLoadItem=function(a){for(var b=this._currentLoads.length,c=0;b>c;c++)if(this._currentLoads[c]==a){this._currentLoads.splice(c,1);break}},b._cleanLoadItem=function(a){var b=a.getItem();b&&delete b._loader},b._handleProgress=function(a){var b=a.target;this._sendFileProgress(b.getItem(),b.progress),this._updateProgress()},b._updateProgress=function(){var a=this._numItemsLoaded/this._numItems,b=this._numItems-this._numItemsLoaded;if(b>0){for(var c=0,d=0,e=this._currentLoads.length;e>d;d++)c+=this._currentLoads[d].progress;a+=c/b*(b/this._numItems)}this._lastProgress!=a&&(this._sendProgress(a),this._lastProgress=a)},b._disposeItem=function(a){delete this._loadedResults[a.id],delete this._loadedRawResults[a.id],delete this._loadItemsById[a.id],delete this._loadItemsBySrc[a.src]},b._sendFileProgress=function(b,c){if(!this._isCanceled()&&!this._paused&&this.hasEventListener("fileprogress")){var d=new a.Event("fileprogress");d.progress=c,d.loaded=c,d.total=1,d.item=b,this.dispatchEvent(d)}},b._sendFileComplete=function(b,c){if(!this._isCanceled()&&!this._paused){var d=new a.Event("fileload");d.loader=c,d.item=b,d.result=this._loadedResults[b.id],d.rawResult=this._loadedRawResults[b.id],b.completeHandler&&b.completeHandler(d),this.hasEventListener("fileload")&&this.dispatchEvent(d)}},b._sendFileStart=function(b){var c=new a.Event("filestart");c.item=b,this.hasEventListener("filestart")&&this.dispatchEvent(c)},b.toString=function(){return"[PreloadJS LoadQueue]"},a.LoadQueue=a.promote(LoadQueue,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function TextLoader(b){this.AbstractLoader_constructor(b,!0,a.AbstractLoader.TEXT)}var b=(a.extend(TextLoader,a.AbstractLoader),TextLoader);b.canLoadItem=function(b){return b.type==a.AbstractLoader.TEXT},a.TextLoader=a.promote(TextLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function BinaryLoader(b){this.AbstractLoader_constructor(b,!0,a.AbstractLoader.BINARY),this.on("initialize",this._updateXHR,this)}var b=a.extend(BinaryLoader,a.AbstractLoader),c=BinaryLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.BINARY},b._updateXHR=function(a){a.loader.setResponseType("arraybuffer")},a.BinaryLoader=a.promote(BinaryLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function CSSLoader(b,c){this.AbstractLoader_constructor(b,c,a.AbstractLoader.CSS),this.resultFormatter=this._formatResult,this._tagSrcAttribute="href",this._tag=document.createElement(c?"style":"link"),this._tag.rel="stylesheet",this._tag.type="text/css"}var b=a.extend(CSSLoader,a.AbstractLoader),c=CSSLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.CSS},b._formatResult=function(b){if(this._preferXHR){var c=b.getTag();if(c.styleSheet)c.styleSheet.cssText=b.getResult(!0);else{var d=document.createTextNode(b.getResult(!0));c.appendChild(d)}}else c=this._tag;return a.DomUtils.appendToHead(c),c},a.CSSLoader=a.promote(CSSLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function ImageLoader(b,c){this.AbstractLoader_constructor(b,c,a.AbstractLoader.IMAGE),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",a.RequestUtils.isImageTag(b)?this._tag=b:a.RequestUtils.isImageTag(b.src)?this._tag=b.src:a.RequestUtils.isImageTag(b.tag)&&(this._tag=b.tag),null!=this._tag?this._preferXHR=!1:this._tag=document.createElement("img"),this.on("initialize",this._updateXHR,this)}var b=a.extend(ImageLoader,a.AbstractLoader),c=ImageLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.IMAGE},b.load=function(){if(""!=this._tag.src&&this._tag.complete)return void this._sendComplete();var b=this._item.crossOrigin;1==b&&(b="Anonymous"),null==b||a.RequestUtils.isLocal(this._item.src)||(this._tag.crossOrigin=b),this.AbstractLoader_load()},b._updateXHR=function(a){a.loader.mimeType="text/plain; charset=x-user-defined-binary",a.loader.setResponseType&&a.loader.setResponseType("blob")},b._formatResult=function(){return this._formatImage},b._formatImage=function(b,c){var d=this._tag,e=window.URL||window.webkitURL;if(this._preferXHR)if(e){var f=e.createObjectURL(this.getResult(!0));d.src=f,d.addEventListener("load",this._cleanUpURL,!1),d.addEventListener("error",this._cleanUpURL,!1)}else d.src=this._item.src;else;d.complete?b(d):(d.onload=a.proxy(function(){b(this._tag)},this),d.onerror=a.proxy(function(){c(_this._tag)},this))},b._cleanUpURL=function(a){var b=window.URL||window.webkitURL;b.revokeObjectURL(a.target.src)},a.ImageLoader=a.promote(ImageLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function JavaScriptLoader(b,c){this.AbstractLoader_constructor(b,c,a.AbstractLoader.JAVASCRIPT),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.setTag(document.createElement("script"))}var b=a.extend(JavaScriptLoader,a.AbstractLoader),c=JavaScriptLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.JAVASCRIPT},b._formatResult=function(a){var b=a.getTag();return this._preferXHR&&(b.text=a.getResult(!0)),b},a.JavaScriptLoader=a.promote(JavaScriptLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function JSONLoader(b){this.AbstractLoader_constructor(b,!0,a.AbstractLoader.JSON),this.resultFormatter=this._formatResult}var b=a.extend(JSONLoader,a.AbstractLoader),c=JSONLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.JSON},b._formatResult=function(b){var c=null;try{c=a.DataUtils.parseJSON(b.getResult(!0))}catch(d){var e=new a.ErrorEvent("JSON_FORMAT",null,d);return this._sendError(e),d}return c},a.JSONLoader=a.promote(JSONLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function JSONPLoader(b){this.AbstractLoader_constructor(b,!1,a.AbstractLoader.JSONP),this.setTag(document.createElement("script")),this.getTag().type="text/javascript"}var b=a.extend(JSONPLoader,a.AbstractLoader),c=JSONPLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.JSONP},b.cancel=function(){this.AbstractLoader_cancel(),this._dispose()},b.load=function(){if(null==this._item.callback)throw new Error("callback is required for loading JSONP requests.");if(null!=window[this._item.callback])throw new Error("JSONP callback '"+this._item.callback+"' already exists on window. You need to specify a different callback or re-name the current one.");window[this._item.callback]=a.proxy(this._handleLoad,this),window.document.body.appendChild(this._tag),this._loadTimeout=setTimeout(a.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag.src=this._item.src},b._handleLoad=function(a){this._result=this._rawResult=a,this._sendComplete(),this._dispose()},b._handleTimeout=function(){this._dispose(),this.dispatchEvent(new a.ErrorEvent("timeout"))},b._dispose=function(){window.document.body.removeChild(this._tag),delete window[this._item.callback],clearTimeout(this._loadTimeout)},a.JSONPLoader=a.promote(JSONPLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function ManifestLoader(b){this.AbstractLoader_constructor(b,null,a.AbstractLoader.MANIFEST),this.plugins=null,this._manifestQueue=null}var b=a.extend(ManifestLoader,a.AbstractLoader),c=ManifestLoader;c.MANIFEST_PROGRESS=.25,c.canLoadItem=function(b){return b.type==a.AbstractLoader.MANIFEST},b.load=function(){this.AbstractLoader_load()},b._createRequest=function(){var b=this._item.callback;this._request=null!=b?new a.JSONPLoader(this._item):new a.JSONLoader(this._item)},b.handleEvent=function(a){switch(a.type){case"complete":return this._rawResult=a.target.getResult(!0),this._result=a.target.getResult(),this._sendProgress(c.MANIFEST_PROGRESS),void this._loadManifest(this._result);case"progress":return a.loaded*=c.MANIFEST_PROGRESS,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0),void this._sendProgress(a)}this.AbstractLoader_handleEvent(a)},b.destroy=function(){this.AbstractLoader_destroy(),this._manifestQueue.close()},b._loadManifest=function(b){if(b&&b.manifest){var c=this._manifestQueue=new a.LoadQueue;c.on("fileload",this._handleManifestFileLoad,this),c.on("progress",this._handleManifestProgress,this),c.on("complete",this._handleManifestComplete,this,!0),c.on("error",this._handleManifestError,this,!0);for(var d=0,e=this.plugins.length;e>d;d++)c.installPlugin(this.plugins[d]);c.loadManifest(b)}else this._sendComplete()},b._handleManifestFileLoad=function(a){a.target=null,this.dispatchEvent(a)},b._handleManifestComplete=function(){this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},b._handleManifestProgress=function(a){this.progress=a.progress*(1-c.MANIFEST_PROGRESS)+c.MANIFEST_PROGRESS,this._sendProgress(this.progress)},b._handleManifestError=function(b){var c=new a.Event("fileerror");c.item=b.data,this.dispatchEvent(c)},a.ManifestLoader=a.promote(ManifestLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function SoundLoader(b,c){this.AbstractMediaLoader_constructor(b,c,a.AbstractLoader.SOUND),a.RequestUtils.isAudioTag(b)?this._tag=b:a.RequestUtils.isAudioTag(b.src)?this._tag=b:a.RequestUtils.isAudioTag(b.tag)&&(this._tag=a.RequestUtils.isAudioTag(b)?b:b.src),null!=this._tag&&(this._preferXHR=!1)}var b=a.extend(SoundLoader,a.AbstractMediaLoader),c=SoundLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.SOUND},b._createTag=function(a){var b=document.createElement("audio");return b.autoplay=!1,b.preload="none",b.src=a,b},a.SoundLoader=a.promote(SoundLoader,"AbstractMediaLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function VideoLoader(b,c){this.AbstractMediaLoader_constructor(b,c,a.AbstractLoader.VIDEO),a.RequestUtils.isVideoTag(b)||a.RequestUtils.isVideoTag(b.src)?(this.setTag(a.RequestUtils.isVideoTag(b)?b:b.src),this._preferXHR=!1):this.setTag(this._createTag())}var b=a.extend(VideoLoader,a.AbstractMediaLoader),c=VideoLoader;b._createTag=function(){return document.createElement("video")},c.canLoadItem=function(b){return b.type==a.AbstractLoader.VIDEO},a.VideoLoader=a.promote(VideoLoader,"AbstractMediaLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function SpriteSheetLoader(b,c){this.AbstractLoader_constructor(b,c,a.AbstractLoader.SPRITESHEET),this._manifestQueue=null}var b=a.extend(SpriteSheetLoader,a.AbstractLoader),c=SpriteSheetLoader;c.SPRITESHEET_PROGRESS=.25,c.canLoadItem=function(b){return b.type==a.AbstractLoader.SPRITESHEET},b.destroy=function(){this.AbstractLoader_destroy,this._manifestQueue.close()},b._createRequest=function(){var b=this._item.callback;this._request=null!=b?new a.JSONPLoader(this._item):new a.JSONLoader(this._item)},b.handleEvent=function(a){switch(a.type){case"complete":return this._rawResult=a.target.getResult(!0),this._result=a.target.getResult(),this._sendProgress(c.SPRITESHEET_PROGRESS),void this._loadManifest(this._result);case"progress":return a.loaded*=c.SPRITESHEET_PROGRESS,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0),void this._sendProgress(a)}this.AbstractLoader_handleEvent(a)},b._loadManifest=function(b){if(b&&b.images){var c=this._manifestQueue=new a.LoadQueue(this._preferXHR,this._item.path,this._item.crossOrigin);c.on("complete",this._handleManifestComplete,this,!0),c.on("fileload",this._handleManifestFileLoad,this),c.on("progress",this._handleManifestProgress,this),c.on("error",this._handleManifestError,this,!0),c.loadManifest(b.images)}},b._handleManifestFileLoad=function(a){var b=a.result;if(null!=b){var c=this.getResult().images,d=c.indexOf(a.item.src);c[d]=b}},b._handleManifestComplete=function(){this._result=new a.SpriteSheet(this._result),this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},b._handleManifestProgress=function(a){this.progress=a.progress*(1-c.SPRITESHEET_PROGRESS)+c.SPRITESHEET_PROGRESS,this._sendProgress(this.progress)},b._handleManifestError=function(b){var c=new a.Event("fileerror");c.item=b.data,this.dispatchEvent(c)},a.SpriteSheetLoader=a.promote(SpriteSheetLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function SVGLoader(b,c){this.AbstractLoader_constructor(b,c,a.AbstractLoader.SVG),this.resultFormatter=this._formatResult,this._tagSrcAttribute="data",c?this.setTag(document.createElement("svg")):(this.setTag(document.createElement("object")),this.getTag().type="image/svg+xml")}var b=a.extend(SVGLoader,a.AbstractLoader),c=SVGLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.SVG},b._formatResult=function(b){var c=a.DataUtils.parseXML(b.getResult(!0),"text/xml"),d=b.getTag();return!this._preferXHR&&document.body.contains(d)&&document.body.removeChild(d),null!=c.documentElement?(d.appendChild(c.documentElement),d.style.visibility="visible",d):c},a.SVGLoader=a.promote(SVGLoader,"AbstractLoader")}(scope.createjs);var scope="undefined"==typeof window?this:window;scope.createjs=scope.createjs||{},function(a){"use strict";function XMLLoader(b){this.AbstractLoader_constructor(b,!0,a.AbstractLoader.XML),this.resultFormatter=this._formatResult}var b=a.extend(XMLLoader,a.AbstractLoader),c=XMLLoader;c.canLoadItem=function(b){return b.type==a.AbstractLoader.XML},b._formatResult=function(b){return a.DataUtils.parseXML(b.getResult(!0),"text/xml")},a.XMLLoader=a.promote(XMLLoader,"AbstractLoader")}(scope.createjs);
\ No newline at end of file
diff --git a/src/createjs/events/ErrorEvent.js b/src/createjs/events/ErrorEvent.js
index 88ed99b..0e7a46e 100644
--- a/src/createjs/events/ErrorEvent.js
+++ b/src/createjs/events/ErrorEvent.js
@@ -1,80 +1,78 @@
/*
-* Event
-* Visit http://createjs.com/ for documentation, updates and examples.
-*
-* Copyright (c) 2010 gskinner.com, inc.
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use,
-* copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following
-* conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*/
+ * Event
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ * Copyright (c) 2010 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
/**
* @module CreateJS
*/
-// namespace:
-this.createjs = this.createjs||{};
+var extend = require('../utils/extend');
+var promote = require('../utils/promote');
+var Event = require('./Event');
-(function() {
- "use strict";
+// namespace:
+/**
+ * A general error {{#crossLink "Event"}}{{/crossLink}}, that describes an error that occurred, as well as any details.
+ * @class ErrorEvent
+ * @param {String} [title] The error title
+ * @param {String} [message] The error description
+ * @param {Object} [data] Additional error data
+ * @constructor
+ */
+function ErrorEvent(title, message, data) {
+ this.Event_constructor("error");
/**
- * A general error {{#crossLink "Event"}}{{/crossLink}}, that describes an error that occurred, as well as any details.
- * @class ErrorEvent
- * @param {String} [title] The error title
- * @param {String} [message] The error description
- * @param {Object} [data] Additional error data
- * @constructor
+ * The short error title, which indicates the type of error that occurred.
+ * @property title
+ * @type String
*/
- function ErrorEvent(title, message, data) {
- this.Event_constructor("error");
-
- /**
- * The short error title, which indicates the type of error that occurred.
- * @property title
- * @type String
- */
- this.title = title;
+ this.title = title;
- /**
- * The verbose error message, containing details about the error.
- * @property message
- * @type String
- */
- this.message = message;
-
- /**
- * Additional data attached to an error.
- * @property data
- * @type {Object}
- */
- this.data = data;
- }
+ /**
+ * The verbose error message, containing details about the error.
+ * @property message
+ * @type String
+ */
+ this.message = message;
- var p = createjs.extend(ErrorEvent, createjs.Event);
+ /**
+ * Additional data attached to an error.
+ * @property data
+ * @type {Object}
+ */
+ this.data = data;
+}
- p.clone = function() {
- return new createjs.ErrorEvent(this.title, this.message, this.data);
- };
+var p = extend(ErrorEvent, Event);
- createjs.ErrorEvent = createjs.promote(ErrorEvent, "Event");
+p.clone = function () {
+ return new ErrorEvent(this.title, this.message, this.data);
+};
-}());
\ No newline at end of file
+var ErrorEvent = promote(ErrorEvent, "Event");
+module.exports = ErrorEvent;
\ No newline at end of file
diff --git a/src/createjs/events/Event.js b/src/createjs/events/Event.js
index 76b6a1d..5075f88 100644
--- a/src/createjs/events/Event.js
+++ b/src/createjs/events/Event.js
@@ -1,30 +1,30 @@
/*
-* Event
-* Visit http://createjs.com/ for documentation, updates and examples.
-*
-* Copyright (c) 2010 gskinner.com, inc.
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use,
-* copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following
-* conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*/
+ * Event
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ * Copyright (c) 2010 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
/**
* A collection of Classes that are shared across all the CreateJS libraries. The classes are included in the minified
@@ -37,227 +37,221 @@
* @module CreateJS
* @main CreateJS
*/
+// constructor:
+/**
+ * Contains properties and methods shared by all events for use with
+ * {{#crossLink "EventDispatcher"}}{{/crossLink}}.
+ *
+ * Note that Event objects are often reused, so you should never
+ * rely on an event object's state outside of the call stack it was received in.
+ * @class Event
+ * @param {String} type The event type.
+ * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
+ * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
+ * @constructor
+ **/
+function Event(type, bubbles, cancelable) {
-// namespace:
-this.createjs = this.createjs||{};
-
-(function() {
- "use strict";
-// constructor:
+ // public properties:
/**
- * Contains properties and methods shared by all events for use with
- * {{#crossLink "EventDispatcher"}}{{/crossLink}}.
- *
- * Note that Event objects are often reused, so you should never
- * rely on an event object's state outside of the call stack it was received in.
- * @class Event
- * @param {String} type The event type.
- * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
- * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
- * @constructor
+ * The type of event.
+ * @property type
+ * @type String
**/
- function Event(type, bubbles, cancelable) {
-
-
- // public properties:
- /**
- * The type of event.
- * @property type
- * @type String
- **/
- this.type = type;
-
- /**
- * The object that generated an event.
- * @property target
- * @type Object
- * @default null
- * @readonly
- */
- this.target = null;
-
- /**
- * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
- * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
- * is generated from childObj, then a listener on parentObj would receive the event with
- * target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
- * @property currentTarget
- * @type Object
- * @default null
- * @readonly
- */
- this.currentTarget = null;
-
- /**
- * For bubbling events, this indicates the current event phase:
- * - capture phase: starting from the top parent to the target
- * - at target phase: currently being dispatched from the target
- * - bubbling phase: from the target to the top parent
- *
- * @property eventPhase
- * @type Number
- * @default 0
- * @readonly
- */
- this.eventPhase = 0;
-
- /**
- * Indicates whether the event will bubble through the display list.
- * @property bubbles
- * @type Boolean
- * @default false
- * @readonly
- */
- this.bubbles = !!bubbles;
-
- /**
- * Indicates whether the default behaviour of this event can be cancelled via
- * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
- * @property cancelable
- * @type Boolean
- * @default false
- * @readonly
- */
- this.cancelable = !!cancelable;
-
- /**
- * The epoch time at which this event was created.
- * @property timeStamp
- * @type Number
- * @default 0
- * @readonly
- */
- this.timeStamp = (new Date()).getTime();
-
- /**
- * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
- * on this event.
- * @property defaultPrevented
- * @type Boolean
- * @default false
- * @readonly
- */
- this.defaultPrevented = false;
-
- /**
- * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
- * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
- * @property propagationStopped
- * @type Boolean
- * @default false
- * @readonly
- */
- this.propagationStopped = false;
-
- /**
- * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
- * on this event.
- * @property immediatePropagationStopped
- * @type Boolean
- * @default false
- * @readonly
- */
- this.immediatePropagationStopped = false;
-
- /**
- * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
- * @property removed
- * @type Boolean
- * @default false
- * @readonly
- */
- this.removed = false;
- }
- var p = Event.prototype;
+ this.type = type;
/**
- * REMOVED. Removed in favor of using `MySuperClass_constructor`.
- * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
- * for details.
- *
- * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
- *
- * @method initialize
- * @protected
- * @deprecated
+ * The object that generated an event.
+ * @property target
+ * @type Object
+ * @default null
+ * @readonly
*/
- // p.initialize = function() {}; // searchable for devs wondering where it is.
-
+ this.target = null;
-// public methods:
/**
- * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true.
- * Mirrors the DOM event standard.
- * @method preventDefault
- **/
- p.preventDefault = function() {
- this.defaultPrevented = this.cancelable&&true;
- };
+ * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
+ * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
+ * is generated from childObj, then a listener on parentObj would receive the event with
+ * target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
+ * @property currentTarget
+ * @type Object
+ * @default null
+ * @readonly
+ */
+ this.currentTarget = null;
/**
- * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
- * Mirrors the DOM event standard.
- * @method stopPropagation
- **/
- p.stopPropagation = function() {
- this.propagationStopped = true;
- };
+ * For bubbling events, this indicates the current event phase:
+ * - capture phase: starting from the top parent to the target
+ * - at target phase: currently being dispatched from the target
+ * - bubbling phase: from the target to the top parent
+ *
+ * @property eventPhase
+ * @type Number
+ * @default 0
+ * @readonly
+ */
+ this.eventPhase = 0;
/**
- * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
- * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
- * Mirrors the DOM event standard.
- * @method stopImmediatePropagation
- **/
- p.stopImmediatePropagation = function() {
- this.immediatePropagationStopped = this.propagationStopped = true;
- };
-
+ * Indicates whether the event will bubble through the display list.
+ * @property bubbles
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.bubbles = !!bubbles;
+
/**
- * Causes the active listener to be removed via removeEventListener();
- *
- * myBtn.addEventListener("click", function(evt) {
- * // do stuff...
- * evt.remove(); // removes this listener.
- * });
- *
- * @method remove
- **/
- p.remove = function() {
- this.removed = true;
- };
-
+ * Indicates whether the default behaviour of this event can be cancelled via
+ * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
+ * @property cancelable
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.cancelable = !!cancelable;
+
/**
- * Returns a clone of the Event instance.
- * @method clone
- * @return {Event} a clone of the Event instance.
- **/
- p.clone = function() {
- return new Event(this.type, this.bubbles, this.cancelable);
- };
-
+ * The epoch time at which this event was created.
+ * @property timeStamp
+ * @type Number
+ * @default 0
+ * @readonly
+ */
+ this.timeStamp = (new Date()).getTime();
+
/**
- * Provides a chainable shortcut method for setting a number of properties on the instance.
- *
- * @method set
- * @param {Object} props A generic object containing properties to copy to the instance.
- * @return {Event} Returns the instance the method is called on (useful for chaining calls.)
- * @chainable
- */
- p.set = function(props) {
- for (var n in props) { this[n] = props[n]; }
- return this;
- };
+ * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
+ * on this event.
+ * @property defaultPrevented
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.defaultPrevented = false;
/**
- * Returns a string representation of this object.
- * @method toString
- * @return {String} a string representation of the instance.
- **/
- p.toString = function() {
- return "[Event (type="+this.type+")]";
- };
+ * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
+ * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
+ * @property propagationStopped
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.propagationStopped = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
+ * on this event.
+ * @property immediatePropagationStopped
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.immediatePropagationStopped = false;
+
+ /**
+ * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
+ * @property removed
+ * @type Boolean
+ * @default false
+ * @readonly
+ */
+ this.removed = false;
+}
+var p = Event.prototype;
+
+/**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+// p.initialize = function() {}; // searchable for devs wondering where it is.
+
+
+// public methods:
+/**
+ * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method preventDefault
+ **/
+p.preventDefault = function () {
+ this.defaultPrevented = this.cancelable && true;
+};
+
+/**
+ * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method stopPropagation
+ **/
+p.stopPropagation = function () {
+ this.propagationStopped = true;
+};
+
+/**
+ * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
+ * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
+ * Mirrors the DOM event standard.
+ * @method stopImmediatePropagation
+ **/
+p.stopImmediatePropagation = function () {
+ this.immediatePropagationStopped = this.propagationStopped = true;
+};
+
+/**
+ * Causes the active listener to be removed via removeEventListener();
+ *
+ * myBtn.addEventListener("click", function(evt) {
+ * // do stuff...
+ * evt.remove(); // removes this listener.
+ * });
+ *
+ * @method remove
+ **/
+p.remove = function () {
+ this.removed = true;
+};
+
+/**
+ * Returns a clone of the Event instance.
+ * @method clone
+ * @return {Event} a clone of the Event instance.
+ **/
+p.clone = function () {
+ return new Event(this.type, this.bubbles, this.cancelable);
+};
+
+/**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the instance.
+ * @return {Event} Returns the instance the method is called on (useful for chaining calls.)
+ * @chainable
+ */
+p.set = function (props) {
+ for (var n in props) {
+ this[n] = props[n];
+ }
+ return this;
+};
+
+/**
+ * Returns a string representation of this object.
+ * @method toString
+ * @return {String} a string representation of the instance.
+ **/
+p.toString = function () {
+ return "[Event (type=" + this.type + ")]";
+};
- createjs.Event = Event;
-}());
+module.exports = Event;
diff --git a/src/createjs/events/EventDispatcher.js b/src/createjs/events/EventDispatcher.js
index 0ae4781..533820b 100644
--- a/src/createjs/events/EventDispatcher.js
+++ b/src/createjs/events/EventDispatcher.js
@@ -1,195 +1,197 @@
/*
-* EventDispatcher
-* Visit http://createjs.com/ for documentation, updates and examples.
-*
-* Copyright (c) 2010 gskinner.com, inc.
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use,
-* copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following
-* conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*/
+ * EventDispatcher
+ * Visit http://createjs.com/ for documentation, updates and examples.
+ *
+ * Copyright (c) 2010 gskinner.com, inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
/**
* @module CreateJS
*/
-// namespace:
-this.createjs = this.createjs||{};
-
-(function() {
- "use strict";
+var Event = require('./Event');
// constructor:
- /**
- * EventDispatcher provides methods for managing queues of event listeners and dispatching events.
- *
- * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
- * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method.
- *
- * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the
- * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports
- * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent.
- *
- * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier
- * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The
- * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to
- * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}.
- *
- * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}}
- * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also
- * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener.
- *
- * Example
- * Add EventDispatcher capabilities to the "MyClass" class.
- *
- * EventDispatcher.initialize(MyClass.prototype);
- *
- * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}).
- *
- * instance.addEventListener("eventName", handlerMethod);
- * function handlerMethod(event) {
+/**
+ * EventDispatcher provides methods for managing queues of event listeners and dispatching events.
+ *
+ * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
+ * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method.
+ *
+ * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the
+ * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports
+ * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent.
+ *
+ * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier
+ * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The
+ * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to
+ * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}.
+ *
+ * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}}
+ * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also
+ * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener.
+ *
+ * Example
+ * Add EventDispatcher capabilities to the "MyClass" class.
+ *
+ * EventDispatcher.initialize(MyClass.prototype);
+ *
+ * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}).
+ *
+ * instance.addEventListener("eventName", handlerMethod);
+ * function handlerMethod(event) {
* console.log(event.target + " Was Clicked");
* }
- *
- * Maintaining proper scope
- * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}}
- * method to subscribe to events simplifies this.
- *
- * instance.addEventListener("click", function(event) {
+ *
+ * Maintaining proper scope
+ * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}}
+ * method to subscribe to events simplifies this.
+ *
+ * instance.addEventListener("click", function(event) {
* console.log(instance == this); // false, scope is ambiguous.
* });
- *
- * instance.on("click", function(event) {
+ *
+ * instance.on("click", function(event) {
* console.log(instance == this); // true, "on" uses dispatcher scope by default.
* });
- *
- * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope.
- *
- *
- * @class EventDispatcher
- * @constructor
- **/
- function EventDispatcher() {
-
-
+ *
+ * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope.
+ *
+ *
+ * @class EventDispatcher
+ * @constructor
+ **/
+function EventDispatcher() {
+
+
// private properties:
- /**
- * @protected
- * @property _listeners
- * @type Object
- **/
- this._listeners = null;
-
- /**
- * @protected
- * @property _captureListeners
- * @type Object
- **/
- this._captureListeners = null;
- }
- var p = EventDispatcher.prototype;
+ /**
+ * @protected
+ * @property _listeners
+ * @type Object
+ **/
+ this._listeners = null;
/**
- * REMOVED. Removed in favor of using `MySuperClass_constructor`.
- * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
- * for details.
- *
- * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
- *
- * @method initialize
* @protected
- * @deprecated
- */
- // p.initialize = function() {}; // searchable for devs wondering where it is.
+ * @property _captureListeners
+ * @type Object
+ **/
+ this._captureListeners = null;
+}
+var p = EventDispatcher.prototype;
+
+/**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+// p.initialize = function() {}; // searchable for devs wondering where it is.
// static public methods:
- /**
- * Static initializer to mix EventDispatcher methods into a target object or prototype.
- *
- * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class
- * EventDispatcher.initialize(myObject); // add to a specific instance
- *
- * @method initialize
- * @static
- * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a
- * prototype.
- **/
- EventDispatcher.initialize = function(target) {
- target.addEventListener = p.addEventListener;
- target.on = p.on;
- target.removeEventListener = target.off = p.removeEventListener;
- target.removeAllEventListeners = p.removeAllEventListeners;
- target.hasEventListener = p.hasEventListener;
- target.dispatchEvent = p.dispatchEvent;
- target._dispatchEvent = p._dispatchEvent;
- target.willTrigger = p.willTrigger;
- };
-
+/**
+ * Static initializer to mix EventDispatcher methods into a target object or prototype.
+ *
+ * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class
+ * EventDispatcher.initialize(myObject); // add to a specific instance
+ *
+ * @method initialize
+ * @static
+ * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a
+ * prototype.
+ **/
+EventDispatcher.initialize = function (target) {
+ target.addEventListener = p.addEventListener;
+ target.on = p.on;
+ target.removeEventListener = target.off = p.removeEventListener;
+ target.removeAllEventListeners = p.removeAllEventListeners;
+ target.hasEventListener = p.hasEventListener;
+ target.dispatchEvent = p.dispatchEvent;
+ target._dispatchEvent = p._dispatchEvent;
+ target.willTrigger = p.willTrigger;
+};
+
// public methods:
- /**
- * Adds the specified event listener. Note that adding multiple listeners to the same function will result in
- * multiple callbacks getting fired.
- *
- * Example
- *
- * displayObject.addEventListener("click", handleClick);
- * function handleClick(event) {
+/**
+ * Adds the specified event listener. Note that adding multiple listeners to the same function will result in
+ * multiple callbacks getting fired.
+ *
+ * Example
+ *
+ * displayObject.addEventListener("click", handleClick);
+ * function handleClick(event) {
* // Click happened.
* }
- *
- * @method addEventListener
- * @param {String} type The string type of the event.
- * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
- * the event is dispatched.
- * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
- * @return {Function | Object} Returns the listener for chaining or assignment.
- **/
- p.addEventListener = function(type, listener, useCapture) {
- var listeners;
- if (useCapture) {
- listeners = this._captureListeners = this._captureListeners||{};
- } else {
- listeners = this._listeners = this._listeners||{};
- }
- var arr = listeners[type];
- if (arr) { this.removeEventListener(type, listener, useCapture); }
- arr = listeners[type]; // remove may have deleted the array
- if (!arr) { listeners[type] = [listener]; }
- else { arr.push(listener); }
- return listener;
- };
-
- /**
- * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener
- * only run once, associate arbitrary data with the listener, and remove the listener.
- *
- * This method works by creating an anonymous wrapper function and subscribing it with addEventListener.
- * The created anonymous function is returned for use with .removeEventListener (or .off).
- *
- * Example
- *
- * var listener = myBtn.on("click", handleClick, null, false, {count:3});
- * function handleClick(evt, data) {
+ *
+ * @method addEventListener
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
+ * the event is dispatched.
+ * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ * @return {Function | Object} Returns the listener for chaining or assignment.
+ **/
+p.addEventListener = function (type, listener, useCapture) {
+ var listeners;
+ if (useCapture) {
+ listeners = this._captureListeners = this._captureListeners || {};
+ } else {
+ listeners = this._listeners = this._listeners || {};
+ }
+ var arr = listeners[type];
+ if (arr) {
+ this.removeEventListener(type, listener, useCapture);
+ }
+ arr = listeners[type]; // remove may have deleted the array
+ if (!arr) {
+ listeners[type] = [listener];
+ }
+ else {
+ arr.push(listener);
+ }
+ return listener;
+};
+
+/**
+ * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener
+ * only run once, associate arbitrary data with the listener, and remove the listener.
+ *
+ * This method works by creating an anonymous wrapper function and subscribing it with addEventListener.
+ * The created anonymous function is returned for use with .removeEventListener (or .off).
+ *
+ * Example
+ *
+ * var listener = myBtn.on("click", handleClick, null, false, {count:3});
+ * function handleClick(evt, data) {
* data.count -= 1;
* console.log(this == myBtn); // true - scope defaults to the dispatcher
* if (data.count == 0) {
@@ -198,210 +200,244 @@ this.createjs = this.createjs||{};
* // alternately: evt.remove();
* }
* }
- *
- * @method on
- * @param {String} type The string type of the event.
- * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
- * the event is dispatched.
- * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent).
- * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered.
- * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called.
- * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
- * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener.
- **/
- p.on = function(type, listener, scope, once, data, useCapture) {
- if (listener.handleEvent) {
- scope = scope||listener;
- listener = listener.handleEvent;
- }
- scope = scope||this;
- return this.addEventListener(type, function(evt) {
- listener.call(scope, evt, data);
- once&&evt.remove();
- }, useCapture);
- };
+ *
+ * @method on
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
+ * the event is dispatched.
+ * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent).
+ * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered.
+ * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called.
+ * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener.
+ **/
+p.on = function (type, listener, scope, once, data, useCapture) {
+ if (listener.handleEvent) {
+ scope = scope || listener;
+ listener = listener.handleEvent;
+ }
+ scope = scope || this;
+ return this.addEventListener(type, function (evt) {
+ listener.call(scope, evt, data);
+ once && evt.remove();
+ }, useCapture);
+};
- /**
- * Removes the specified event listener.
- *
- * Important Note: that you must pass the exact function reference used when the event was added. If a proxy
- * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or
- * closure will not work.
- *
- * Example
- *
- * displayObject.removeEventListener("click", handleClick);
- *
- * @method removeEventListener
- * @param {String} type The string type of the event.
- * @param {Function | Object} listener The listener function or object.
- * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
- **/
- p.removeEventListener = function(type, listener, useCapture) {
- var listeners = useCapture ? this._captureListeners : this._listeners;
- if (!listeners) { return; }
- var arr = listeners[type];
- if (!arr) { return; }
- for (var i=0,l=arr.length; iImportant Note: that you must pass the exact function reference used when the event was added. If a proxy
+ * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or
+ * closure will not work.
+ *
+ * Example
+ *
+ * displayObject.removeEventListener("click", handleClick);
+ *
+ * @method removeEventListener
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener The listener function or object.
+ * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ **/
+p.removeEventListener = function (type, listener, useCapture) {
+ var listeners = useCapture ? this._captureListeners : this._listeners;
+ if (!listeners) {
+ return;
+ }
+ var arr = listeners[type];
+ if (!arr) {
+ return;
+ }
+ for (var i = 0, l = arr.length; i < l; i++) {
+ if (arr[i] == listener) {
+ if (l == 1) {
+ delete(listeners[type]);
+ } // allows for faster checks.
+ else {
+ arr.splice(i, 1);
}
+ break;
}
- };
-
- /**
- * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the
- * .on method.
- *
- * @method off
- * @param {String} type The string type of the event.
- * @param {Function | Object} listener The listener function or object.
- * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
- **/
- p.off = p.removeEventListener;
+ }
+};
- /**
- * Removes all listeners for the specified type, or all listeners of all types.
- *
- * Example
- *
- * // Remove all listeners
- * displayObject.removeAllEventListeners();
- *
- * // Remove all click listeners
- * displayObject.removeAllEventListeners("click");
- *
- * @method removeAllEventListeners
- * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed.
- **/
- p.removeAllEventListeners = function(type) {
- if (!type) { this._listeners = this._captureListeners = null; }
- else {
- if (this._listeners) { delete(this._listeners[type]); }
- if (this._captureListeners) { delete(this._captureListeners[type]); }
+/**
+ * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the
+ * .on method.
+ *
+ * @method off
+ * @param {String} type The string type of the event.
+ * @param {Function | Object} listener The listener function or object.
+ * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
+ **/
+p.off = p.removeEventListener;
+
+/**
+ * Removes all listeners for the specified type, or all listeners of all types.
+ *
+ * Example
+ *
+ * // Remove all listeners
+ * displayObject.removeAllEventListeners();
+ *
+ * // Remove all click listeners
+ * displayObject.removeAllEventListeners("click");
+ *
+ * @method removeAllEventListeners
+ * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed.
+ **/
+p.removeAllEventListeners = function (type) {
+ if (!type) {
+ this._listeners = this._captureListeners = null;
+ }
+ else {
+ if (this._listeners) {
+ delete(this._listeners[type]);
+ }
+ if (this._captureListeners) {
+ delete(this._captureListeners[type]);
}
- };
+ }
+};
- /**
- * Dispatches the specified event to all listeners.
- *
- * Example
- *
- * // Use a string event
- * this.dispatchEvent("complete");
- *
- * // Use an Event instance
- * var event = new createjs.Event("progress");
- * this.dispatchEvent(event);
- *
- * @method dispatchEvent
- * @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
- * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
- * dispatchEvent will construct an Event instance with the specified type.
- * @return {Boolean} Returns the value of eventObj.defaultPrevented.
- **/
- p.dispatchEvent = function(eventObj) {
- if (typeof eventObj == "string") {
- // won't bubble, so skip everything if there's no listeners:
- var listeners = this._listeners;
- if (!listeners || !listeners[eventObj]) { return false; }
- eventObj = new createjs.Event(eventObj);
- } else if (eventObj.target && eventObj.clone) {
- // redispatching an active event object, so clone it:
- eventObj = eventObj.clone();
+/**
+ * Dispatches the specified event to all listeners.
+ *
+ * Example
+ *
+ * // Use a string event
+ * this.dispatchEvent("complete");
+ *
+ * // Use an Event instance
+ * var event = new createjs.Event("progress");
+ * this.dispatchEvent(event);
+ *
+ * @method dispatchEvent
+ * @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
+ * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
+ * dispatchEvent will construct an Event instance with the specified type.
+ * @return {Boolean} Returns the value of eventObj.defaultPrevented.
+ **/
+p.dispatchEvent = function (eventObj) {
+ if (typeof eventObj == "string") {
+ // won't bubble, so skip everything if there's no listeners:
+ var listeners = this._listeners;
+ if (!listeners || !listeners[eventObj]) {
+ return false;
}
- try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events
+ eventObj = new Event(eventObj);
+ } else if (eventObj.target && eventObj.clone) {
+ // redispatching an active event object, so clone it:
+ eventObj = eventObj.clone();
+ }
+ try {
+ eventObj.target = this;
+ } catch (e) {
+ } // try/catch allows redispatching of native events
- if (!eventObj.bubbles || !this.parent) {
- this._dispatchEvent(eventObj, 2);
- } else {
- var top=this, list=[top];
- while (top.parent) { list.push(top = top.parent); }
- var i, l=list.length;
+ if (!eventObj.bubbles || !this.parent) {
+ this._dispatchEvent(eventObj, 2);
+ } else {
+ var top = this, list = [top];
+ while (top.parent) {
+ list.push(top = top.parent);
+ }
+ var i, l = list.length;
- // capture & atTarget
- for (i=l-1; i>=0 && !eventObj.propagationStopped; i--) {
- list[i]._dispatchEvent(eventObj, 1+(i==0));
- }
- // bubbling
- for (i=1; i= 0 && !eventObj.propagationStopped; i--) {
+ list[i]._dispatchEvent(eventObj, 1 + (i == 0));
+ }
+ // bubbling
+ for (i = 1; i < l && !eventObj.propagationStopped; i++) {
+ list[i]._dispatchEvent(eventObj, 3);
}
- return eventObj.defaultPrevented;
- };
+ }
+ return eventObj.defaultPrevented;
+};
- /**
- * Indicates whether there is at least one listener for the specified event type.
- * @method hasEventListener
- * @param {String} type The string type of the event.
- * @return {Boolean} Returns true if there is at least one listener for the specified event.
- **/
- p.hasEventListener = function(type) {
- var listeners = this._listeners, captureListeners = this._captureListeners;
- return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type]));
- };
-
- /**
- * Indicates whether there is at least one listener for the specified event type on this object or any of its
- * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the
- * specified type is dispatched from this object, it will trigger at least one listener.
- *
- * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire
- * event flow for a listener, not just this object.
- * @method willTrigger
- * @param {String} type The string type of the event.
- * @return {Boolean} Returns `true` if there is at least one listener for the specified event.
- **/
- p.willTrigger = function(type) {
- var o = this;
- while (o) {
- if (o.hasEventListener(type)) { return true; }
- o = o.parent;
+/**
+ * Indicates whether there is at least one listener for the specified event type.
+ * @method hasEventListener
+ * @param {String} type The string type of the event.
+ * @return {Boolean} Returns true if there is at least one listener for the specified event.
+ **/
+p.hasEventListener = function (type) {
+ var listeners = this._listeners, captureListeners = this._captureListeners;
+ return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type]));
+};
+
+/**
+ * Indicates whether there is at least one listener for the specified event type on this object or any of its
+ * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the
+ * specified type is dispatched from this object, it will trigger at least one listener.
+ *
+ * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire
+ * event flow for a listener, not just this object.
+ * @method willTrigger
+ * @param {String} type The string type of the event.
+ * @return {Boolean} Returns `true` if there is at least one listener for the specified event.
+ **/
+p.willTrigger = function (type) {
+ var o = this;
+ while (o) {
+ if (o.hasEventListener(type)) {
+ return true;
}
- return false;
- };
+ o = o.parent;
+ }
+ return false;
+};
- /**
- * @method toString
- * @return {String} a string representation of the instance.
- **/
- p.toString = function() {
- return "[EventDispatcher]";
- };
+/**
+ * @method toString
+ * @return {String} a string representation of the instance.
+ **/
+p.toString = function () {
+ return "[EventDispatcher]";
+};
// private methods:
- /**
- * @method _dispatchEvent
- * @param {Object | String | Event} eventObj
- * @param {Object} eventPhase
- * @protected
- **/
- p._dispatchEvent = function(eventObj, eventPhase) {
- var l, listeners = (eventPhase==1) ? this._captureListeners : this._listeners;
- if (eventObj && listeners) {
- var arr = listeners[eventObj.type];
- if (!arr||!(l=arr.length)) { return; }
- try { eventObj.currentTarget = this; } catch (e) {}
- try { eventObj.eventPhase = eventPhase; } catch (e) {}
- eventObj.removed = false;
-
- arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
- for (var i=0; iExample
- *
- * myObject.addEventListener("event", createjs.proxy(myHandler, this, arg1, arg2));
- *
- * function myHandler(arg1, arg2) {
+/**
+ * A function proxy for methods. By default, JavaScript methods do not maintain scope, so passing a method as a
+ * callback will result in the method getting called in the scope of the caller. Using a proxy ensures that the
+ * method gets called in the correct scope.
+ *
+ * Additional arguments can be passed that will be applied to the function when it is called.
+ *
+ * Example
+ *
+ * myObject.addEventListener("event", createjs.proxy(myHandler, this, arg1, arg2));
+ *
+ * function myHandler(arg1, arg2) {
* // This gets called when myObject.myCallback is executed.
* }
- *
- * @method proxy
- * @param {Function} method The function to call
- * @param {Object} scope The scope to call the method name on
- * @param {mixed} [arg] * Arguments that are appended to the callback for additional params.
- * @public
- * @static
- */
- createjs.proxy = function (method, scope) {
- var aArgs = Array.prototype.slice.call(arguments, 2);
- return function () {
- return method.apply(scope, Array.prototype.slice.call(arguments, 0).concat(aArgs));
- };
- }
-
-}());
+ *
+ * @method proxy
+ * @param {Function} method The function to call
+ * @param {Object} scope The scope to call the method name on
+ * @param {mixed} [arg] * Arguments that are appended to the callback for additional params.
+ * @public
+ * @static
+ */
+module.exports = function (method, scope) {
+ var aArgs = Array.prototype.slice.call(arguments, 2);
+ return function () {
+ return method.apply(scope, Array.prototype.slice.call(arguments, 0).concat(aArgs));
+ };
+}
\ No newline at end of file
diff --git a/src/preloadjs/LoadQueue.js b/src/preloadjs/LoadQueue.js
index 6e4e1e2..0aa512b 100644
--- a/src/preloadjs/LoadQueue.js
+++ b/src/preloadjs/LoadQueue.js
@@ -88,7 +88,7 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+
/*
TODO: WINDOWS ISSUES
@@ -102,112 +102,109 @@ this.createjs = this.createjs || {};
* Reported issues with IE7/8
*/
-(function () {
- "use strict";
-
// constructor
- /**
- * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either
- * a single file, or queue of files.
- *
- * Creating a Queue
- * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR
- * argument to false.
- *
- * var queue = new createjs.LoadQueue(true);
- *
- * Listening for Events
- * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}}
- * lets you add as many listeners as you want for events. You can subscribe to the following events:
- * - {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all
- * files
- * - {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with
- * any file.
- * - {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has
- * changed.
- * - {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
- * - {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note
- * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
- *
- *
- * queue.on("fileload", handleFileLoad, this);
- * queue.on("complete", handleComplete, this);
- *
- * Adding files and manifests
- * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a
- * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are
- * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you
- * like.
- *
- * queue.loadFile("filePath/file.jpg");
- * queue.loadFile({id:"image", src:"filePath/file.jpg"});
- * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]);
- *
- * // Use an external manifest
- * queue.loadManifest("path/to/manifest.json");
- * queue.loadManifest({src:"manifest.json", type:"manifest"});
- *
- * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not
- * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin
- * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a
- * `loadNow` argument of `true`.
- *
- * queue.load();
- *
- * File Types
- * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS
- * should handle the majority of standard file and url formats, and works with common file extensions. If you have
- * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a
- * type
property with any manifest item.
- *
- * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.AbstractLoader.SOUND});
- *
- * // Note that PreloadJS will not read a file extension from the query string
- * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.AbstractLoader.IMAGE});
- *
- * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
- *
- * - {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
- * - {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files
- * - {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats
- * - {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
- * - {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data
- * - {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
- * - {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see
- * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
- * - {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats
- * - {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This
- * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
- * - {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files
- * - {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only
- * - {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}: Video objects
- * - {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data
- *
- *
- * Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better
- * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but
- * are deprecated.
- *
- * Handling Results
- * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is
- * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a
- * formatted object that can be used immediately, including:
- *
- * - Binary: The binary loaded result
- * - CSS: A <link /> tag
- * - Image: An <img /> tag
- * - JavaScript: A <script /> tag
- * - JSON/JSONP: A formatted JavaScript Object
- * - Manifest: A JavaScript object.
- *
- Sound: An <audio /> tag
- *
- SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images.
- *
- SVG: An <object /> tag
- * - Text: Raw text
- * - Video: A Video DOM node
- * - XML: An XML DOM node
- *
- *
- * function handleFileLoad(event) {
+/**
+ * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either
+ * a single file, or queue of files.
+ *
+ * Creating a Queue
+ * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR
+ * argument to false.
+ *
+ * var queue = new createjs.LoadQueue(true);
+ *
+ * Listening for Events
+ * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}}
+ * lets you add as many listeners as you want for events. You can subscribe to the following events:
+ * - {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all
+ * files
+ * - {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with
+ * any file.
+ * - {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has
+ * changed.
+ * - {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
+ * - {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note
+ * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
+ *
+ *
+ * queue.on("fileload", handleFileLoad, this);
+ * queue.on("complete", handleComplete, this);
+ *
+ * Adding files and manifests
+ * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a
+ * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are
+ * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you
+ * like.
+ *
+ * queue.loadFile("filePath/file.jpg");
+ * queue.loadFile({id:"image", src:"filePath/file.jpg"});
+ * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]);
+ *
+ * // Use an external manifest
+ * queue.loadManifest("path/to/manifest.json");
+ * queue.loadManifest({src:"manifest.json", type:"manifest"});
+ *
+ * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not
+ * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin
+ * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a
+ * `loadNow` argument of `true`.
+ *
+ * queue.load();
+ *
+ * File Types
+ * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS
+ * should handle the majority of standard file and url formats, and works with common file extensions. If you have
+ * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a
+ * type
property with any manifest item.
+ *
+ * queue.loadFile({src:"path/to/myFile.mp3x", type:AbstractLoader.SOUND});
+ *
+ * // Note that PreloadJS will not read a file extension from the query string
+ * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:AbstractLoader.IMAGE});
+ *
+ * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
+ *
+ * - {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
+ * - {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files
+ * - {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats
+ * - {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
+ * - {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data
+ * - {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
+ * - {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see
+ * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
+ * - {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats
+ * - {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This
+ * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
+ * - {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files
+ * - {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only
+ * - {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}: Video objects
+ * - {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data
+ *
+ *
+ * Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better
+ * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but
+ * are deprecated.
+ *
+ * Handling Results
+ * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is
+ * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a
+ * formatted object that can be used immediately, including:
+ *
+ * - Binary: The binary loaded result
+ * - CSS: A <link /> tag
+ * - Image: An <img /> tag
+ * - JavaScript: A <script /> tag
+ * - JSON/JSONP: A formatted JavaScript Object
+ * - Manifest: A JavaScript object.
+ *
- Sound: An <audio /> tag
+ *
- SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images.
+ *
- SVG: An <object /> tag
+ * - Text: Raw text
+ * - Video: A Video DOM node
+ * - XML: An XML DOM node
+ *
+ *
+ * function handleFileLoad(event) {
* var item = event.item; // A reference to the item that was passed in to the LoadQueue
* var type = item.type;
*
@@ -216,1736 +213,1749 @@ this.createjs = this.createjs || {};
* document.body.appendChild(event.result);
* }
* }
- *
- * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up
- * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the
- * "src" or file path can be used instead, including the `path` defined by a manifest, but not including
- * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content.
- *
- * var image = queue.getResult("image");
- * document.body.appendChild(image);
- *
- * Raw loaded content can be accessed using the rawResult
property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
- * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
- * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
- * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
- *
- * var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
- *
- * Plugins
- * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio,
- * make sure to install the SoundJS Sound class, which will help load HTML audio,
- * Flash audio, and WebAudio files. This should be installed before loading any audio files.
- *
- * queue.installPlugin(createjs.Sound);
- *
- * Known Browser Issues
- *
- * - Browsers without audio support can not load audio files.
- * - Safari on Mac OS X can only play HTML audio if QuickTime is installed
- * - HTML Audio tags will only download until their
canPlayThrough
event is fired. Browsers other
- * than Chrome will continue to download in the background.
- * - When loading scripts using tags, they are automatically added to the document.
- * - Scripts loaded via XHR may not be properly inspectable with browser tools.
- * - IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require
- * XHR to work.
- * - Content loaded via tags will not show progress, and will continue to download in the background when
- * canceled, although no events will be dispatched.
- *
- *
- * @class LoadQueue
- * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP
- * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR
- * when necessary.
- * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue
- * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../`
- * will not receive a base path.
- * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To
- * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any
- * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin
- * parameter is deprecated. Use LoadItem.crossOrigin instead
- *
- * @constructor
- * @extends AbstractLoader
- */
- function LoadQueue (preferXHR, basePath, crossOrigin) {
- this.AbstractLoader_constructor();
-
- /**
- * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}.
- * @property _plugins
- * @type {Array}
- * @private
- * @since 0.6.1
- */
- this._plugins = [];
-
- /**
- * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the
- * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
- * method for more information.
- * @property _typeCallbacks
- * @type {Object}
- * @private
- */
- this._typeCallbacks = {};
-
- /**
- * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the
- * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
- * method for more information.
- * @property _extensionCallbacks
- * @type {null}
- * @private
- */
- this._extensionCallbacks = {};
-
- /**
- * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and
- * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed.
- * @property next
- * @type {LoadQueue}
- * @default null
- */
- this.next = null;
-
- /**
- * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head
- * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas
- * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order
- * specified.
- *
- * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}}
- * property on the load item, or by ensuring that only one connection can be open at a time using
- * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property
- * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the
- * `maintainScriptOrder` to `false` during a load will not change items already in a queue.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.setMaxConnections(3); // Set a higher number to load multiple items at once
- * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order
- * queue.loadManifest([
- * "script1.js",
- * "script2.js",
- * "image.png", // Load any time
- * {src: "image2.png", maintainOrder: true} // Will wait for script2.js
- * "image3.png",
- * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR)
- * ]);
- *
- * @property maintainScriptOrder
- * @type {Boolean}
- * @default true
- */
- this.maintainScriptOrder = true;
-
- /**
- * Determines if the LoadQueue will stop processing the current queue when an error is encountered.
- * @property stopOnError
- * @type {Boolean}
- * @default false
- */
- this.stopOnError = false;
-
- /**
- * The number of maximum open connections that a loadQueue tries to maintain. Please see
- * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information.
- * @property _maxConnections
- * @type {Number}
- * @default 1
- * @private
- */
- this._maxConnections = 1;
-
- /**
- * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the
- * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can
- * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is
- * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the
- * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of
- * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}.
- *
- * Loaders can be removed from PreloadJS by simply not including them.
- *
- * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list
- * so that they are checked first.
- * @property _availableLoaders
- * @type {Array}
- * @private
- * @since 0.6.0
- */
- this._availableLoaders = [
- createjs.ImageLoader,
- createjs.JavaScriptLoader,
- createjs.CSSLoader,
- createjs.JSONLoader,
- createjs.JSONPLoader,
- createjs.SoundLoader,
- createjs.ManifestLoader,
- createjs.SpriteSheetLoader,
- createjs.XMLLoader,
- createjs.SVGLoader,
- createjs.BinaryLoader,
- createjs.VideoLoader,
- createjs.TextLoader
- ];
-
- /**
- * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}.
- * @property _defaultLoaderLength
- * @type {Number}
- * @private
- * @since 0.6.0
- */
- this._defaultLoaderLength = this._availableLoaders.length;
+ *
+ * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up
+ * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the
+ * "src" or file path can be used instead, including the `path` defined by a manifest, but not including
+ * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content.
+ *
+ * var image = queue.getResult("image");
+ * document.body.appendChild(image);
+ *
+ * Raw loaded content can be accessed using the rawResult
property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
+ * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
+ * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
+ *
+ * var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
+ *
+ * Plugins
+ * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio,
+ * make sure to install the SoundJS Sound class, which will help load HTML audio,
+ * Flash audio, and WebAudio files. This should be installed before loading any audio files.
+ *
+ * queue.installPlugin(createjs.Sound);
+ *
+ * Known Browser Issues
+ *
+ * - Browsers without audio support can not load audio files.
+ * - Safari on Mac OS X can only play HTML audio if QuickTime is installed
+ * - HTML Audio tags will only download until their
canPlayThrough
event is fired. Browsers other
+ * than Chrome will continue to download in the background.
+ * - When loading scripts using tags, they are automatically added to the document.
+ * - Scripts loaded via XHR may not be properly inspectable with browser tools.
+ * - IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require
+ * XHR to work.
+ * - Content loaded via tags will not show progress, and will continue to download in the background when
+ * canceled, although no events will be dispatched.
+ *
+ *
+ * @class LoadQueue
+ * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP
+ * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR
+ * when necessary.
+ * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue
+ * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../`
+ * will not receive a base path.
+ * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To
+ * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any
+ * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin
+ * parameter is deprecated. Use LoadItem.crossOrigin instead
+ *
+ * @constructor
+ * @extends AbstractLoader
+ */
- this.init(preferXHR, basePath, crossOrigin);
- }
+var ImageLoader = require('./loaders/ImageLoader');
+var extend = require('../createjs/utils/extend');
+var promote = require('../createjs/utils/promote');
+var AbstractLoader = require('./loaders/AbstractLoader');
+var Event = require('../createjs/events/Event');
+var ErrorEvent = require('../createjs/events/ErrorEvent');
+var RequestUtils = require('./utils/RequestUtils');
+var LoadItem = require('./data/LoadItem');
- var p = createjs.extend(LoadQueue, createjs.AbstractLoader);
- var s = LoadQueue;
+function LoadQueue(preferXHR, basePath, crossOrigin) {
+ this.AbstractLoader_constructor();
/**
- * REMOVED. Removed in favor of using `MySuperClass_constructor`.
- * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
- * for details.
- *
- * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
- *
- * @method initialize
- * @protected
- * @deprecated
+ * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}.
+ * @property _plugins
+ * @type {Array}
+ * @private
+ * @since 0.6.1
*/
- // p.initialize = function() {}; // searchable for devs wondering where it is.
+ this._plugins = [];
/**
- * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue.
- * @method init
- * @param preferXHR
- * @param basePath
- * @param crossOrigin
+ * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the
+ * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
+ * method for more information.
+ * @property _typeCallbacks
+ * @type {Object}
* @private
*/
- p.init = function (preferXHR, basePath, crossOrigin) {
-
- // public properties
- /**
- * @property useXHR
- * @type {Boolean}
- * @readonly
- * @default true
- * @deprecated Use preferXHR instead.
- */
- this.useXHR = true;
-
- /**
- * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR
- * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR,
- * and plain text can not be loaded with tags, so it will default the the correct type instead of using the
- * user-defined type.
- * @type {Boolean}
- * @default true
- * @since 0.6.0
- */
- this.preferXHR = true; //TODO: Get/Set
- this._preferXHR = true;
- this.setPreferXHR(preferXHR);
-
- // protected properties
- /**
- * Whether the queue is currently paused or not.
- * @property _paused
- * @type {boolean}
- * @private
- */
- this._paused = false;
-
- /**
- * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The
- * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such
- * as `http://`, or a relative path such as `../`.
- * @property _basePath
- * @type {String}
- * @private
- * @since 0.3.1
- */
- this._basePath = basePath;
-
- /**
- * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded
- * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by
- * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues,
- * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are ""
- * and "Anonymous".
- * @property _crossOrigin
- * @type {String}
- * @default ""
- * @private
- * @since 0.4.1
- */
- this._crossOrigin = crossOrigin;
-
- /**
- * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first
- * file is requested.
- * @property _loadStartWasDispatched
- * @type {Boolean}
- * @default false
- * @private
- */
- this._loadStartWasDispatched = false;
-
- /**
- * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when
- * using a script tag to do preloading.
- * @property _currentlyLoadingScript
- * @type {Boolean}
- * @private
- */
- this._currentlyLoadingScript = null;
-
- /**
- * An array containing the currently downloading files.
- * @property _currentLoads
- * @type {Array}
- * @private
- */
- this._currentLoads = [];
-
- /**
- * An array containing the queued items that have not yet started downloading.
- * @property _loadQueue
- * @type {Array}
- * @private
- */
- this._loadQueue = [];
-
- /**
- * An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
- * @property _loadQueueBackup
- * @type {Array}
- * @private
- */
- this._loadQueueBackup = [];
-
- /**
- * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}}
- * id.
- * @property _loadItemsById
- * @type {Object}
- * @private
- */
- this._loadItemsById = {};
-
- /**
- * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}}
- * source.
- * @property _loadItemsBySrc
- * @type {Object}
- * @private
- */
- this._loadItemsBySrc = {};
-
- /**
- * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
- * @property _loadedResults
- * @type {Object}
- * @private
- */
- this._loadedResults = {};
-
- /**
- * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
- * @property _loadedRawResults
- * @type {Object}
- * @private
- */
- this._loadedRawResults = {};
-
- /**
- * The number of items that have been requested. This helps manage an overall progress without knowing how large
- * the files are before they are downloaded. This does not include items inside of loaders such as the
- * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
- * @property _numItems
- * @type {Number}
- * @default 0
- * @private
- */
- this._numItems = 0;
-
- /**
- * The number of items that have completed loaded. This helps manage an overall progress without knowing how large
- * the files are before they are downloaded.
- * @property _numItemsLoaded
- * @type {Number}
- * @default 0
- * @private
- */
- this._numItemsLoaded = 0;
-
- /**
- * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right
- * order.
- * @property _scriptOrder
- * @type {Array}
- * @private
- */
- this._scriptOrder = [];
-
- /**
- * A list of scripts that have been loaded. Items are added to this list as null
when they are
- * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true
- * once they are complete and have been dispatched.
- * @property _loadedScripts
- * @type {Array}
- * @private
- */
- this._loadedScripts = [];
-
- /**
- * The last progress amount. This is used to suppress duplicate progress events.
- * @property _lastProgress
- * @type {Number}
- * @private
- * @since 0.6.0
- */
- this._lastProgress = NaN;
-
- };
+ this._typeCallbacks = {};
-// static properties
/**
- * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
- * event is dispatched if the timeout is reached before any data is received.
- * @property loadTimeout
- * @type {Number}
- * @default 8000
- * @static
- * @since 0.4.1
- * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
+ * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the
+ * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
+ * method for more information.
+ * @property _extensionCallbacks
+ * @type {null}
+ * @private
*/
- s.loadTimeout = 8000;
+ this._extensionCallbacks = {};
/**
- * The time in milliseconds to assume a load has failed.
- * @property LOAD_TIMEOUT
- * @type {Number}
- * @default 0
- * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
+ * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and
+ * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed.
+ * @property next
+ * @type {LoadQueue}
+ * @default null
*/
- s.LOAD_TIMEOUT = 0;
+ this.next = null;
-// Preload Types
/**
- * @property BINARY
- * @type {String}
- * @default binary
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
+ * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head
+ * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas
+ * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order
+ * specified.
+ *
+ * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}}
+ * property on the load item, or by ensuring that only one connection can be open at a time using
+ * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property
+ * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the
+ * `maintainScriptOrder` to `false` during a load will not change items already in a queue.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(3); // Set a higher number to load multiple items at once
+ * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order
+ * queue.loadManifest([
+ * "script1.js",
+ * "script2.js",
+ * "image.png", // Load any time
+ * {src: "image2.png", maintainOrder: true} // Will wait for script2.js
+ * "image3.png",
+ * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR)
+ * ]);
+ *
+ * @property maintainScriptOrder
+ * @type {Boolean}
+ * @default true
*/
- s.BINARY = createjs.AbstractLoader.BINARY;
+ this.maintainScriptOrder = true;
/**
- * @property CSS
- * @type {String}
- * @default css
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ * Determines if the LoadQueue will stop processing the current queue when an error is encountered.
+ * @property stopOnError
+ * @type {Boolean}
+ * @default false
*/
- s.CSS = createjs.AbstractLoader.CSS;
+ this.stopOnError = false;
/**
- * @property IMAGE
- * @type {String}
- * @default image
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ * The number of maximum open connections that a loadQueue tries to maintain. Please see
+ * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information.
+ * @property _maxConnections
+ * @type {Number}
+ * @default 1
+ * @private
*/
- s.IMAGE = createjs.AbstractLoader.IMAGE;
+ this._maxConnections = 1;
/**
- * @property JAVASCRIPT
- * @type {String}
- * @default javascript
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the
+ * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can
+ * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is
+ * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the
+ * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of
+ * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}.
+ *
+ * Loaders can be removed from PreloadJS by simply not including them.
+ *
+ * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list
+ * so that they are checked first.
+ * @property _availableLoaders
+ * @type {Array}
+ * @private
+ * @since 0.6.0
*/
- s.JAVASCRIPT = createjs.AbstractLoader.JAVASCRIPT;
+ this._availableLoaders = [
+ ImageLoader
+ /*,
+ createjs.JavaScriptLoader,
+ createjs.CSSLoader,
+ createjs.JSONLoader,
+ createjs.JSONPLoader,
+ createjs.SoundLoader,
+ createjs.ManifestLoader,
+ createjs.SpriteSheetLoader,
+ createjs.XMLLoader,
+ createjs.SVGLoader,
+ createjs.BinaryLoader,
+ createjs.VideoLoader,
+ createjs.TextLoader
+ */
+ ];
/**
- * @property JSON
- * @type {String}
- * @default json
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
+ * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}.
+ * @property _defaultLoaderLength
+ * @type {Number}
+ * @private
+ * @since 0.6.0
*/
- s.JSON = createjs.AbstractLoader.JSON;
+ this._defaultLoaderLength = this._availableLoaders.length;
+
+ this.init(preferXHR, basePath, crossOrigin);
+}
+
+var p = extend(LoadQueue, AbstractLoader);
+var s = LoadQueue;
+
+/**
+ * REMOVED. Removed in favor of using `MySuperClass_constructor`.
+ * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
+ * for details.
+ *
+ * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
+ *
+ * @method initialize
+ * @protected
+ * @deprecated
+ */
+// p.initialize = function() {}; // searchable for devs wondering where it is.
+/**
+ * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue.
+ * @method init
+ * @param preferXHR
+ * @param basePath
+ * @param crossOrigin
+ * @private
+ */
+p.init = function (preferXHR, basePath, crossOrigin) {
+
+ // public properties
/**
- * @property JSONP
- * @type {String}
- * @default jsonp
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
+ * @property useXHR
+ * @type {Boolean}
+ * @readonly
+ * @default true
+ * @deprecated Use preferXHR instead.
*/
- s.JSONP = createjs.AbstractLoader.JSONP;
+ this.useXHR = true;
/**
- * @property MANIFEST
- * @type {String}
- * @default manifest
- * @static
- * @since 0.4.1
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
+ * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR
+ * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR,
+ * and plain text can not be loaded with tags, so it will default the the correct type instead of using the
+ * user-defined type.
+ * @type {Boolean}
+ * @default true
+ * @since 0.6.0
*/
- s.MANIFEST = createjs.AbstractLoader.MANIFEST;
+ this.preferXHR = true; //TODO: Get/Set
+ this._preferXHR = true;
+ this.setPreferXHR(preferXHR);
+ // protected properties
/**
- * @property SOUND
- * @type {String}
- * @default sound
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ * Whether the queue is currently paused or not.
+ * @property _paused
+ * @type {boolean}
+ * @private
*/
- s.SOUND = createjs.AbstractLoader.SOUND;
+ this._paused = false;
/**
- * @property VIDEO
+ * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The
+ * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such
+ * as `http://`, or a relative path such as `../`.
+ * @property _basePath
* @type {String}
- * @default video
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ * @private
+ * @since 0.3.1
*/
- s.VIDEO = createjs.AbstractLoader.VIDEO;
+ this._basePath = basePath;
/**
- * @property SVG
+ * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded
+ * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by
+ * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues,
+ * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are ""
+ * and "Anonymous".
+ * @property _crossOrigin
* @type {String}
- * @default svg
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
+ * @default ""
+ * @private
+ * @since 0.4.1
*/
- s.SVG = createjs.AbstractLoader.SVG;
+ this._crossOrigin = crossOrigin;
/**
- * @property TEXT
- * @type {String}
- * @default text
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
+ * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first
+ * file is requested.
+ * @property _loadStartWasDispatched
+ * @type {Boolean}
+ * @default false
+ * @private
*/
- s.TEXT = createjs.AbstractLoader.TEXT;
+ this._loadStartWasDispatched = false;
/**
- * @property XML
- * @type {String}
- * @default xml
- * @static
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
+ * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when
+ * using a script tag to do preloading.
+ * @property _currentlyLoadingScript
+ * @type {Boolean}
+ * @private
*/
- s.XML = createjs.AbstractLoader.XML;
+ this._currentlyLoadingScript = null;
/**
- * @property POST
- * @type {string}
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
+ * An array containing the currently downloading files.
+ * @property _currentLoads
+ * @type {Array}
+ * @private
*/
- s.POST = createjs.AbstractLoader.POST;
+ this._currentLoads = [];
/**
- * @property GET
- * @type {string}
- * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
+ * An array containing the queued items that have not yet started downloading.
+ * @property _loadQueue
+ * @type {Array}
+ * @private
*/
- s.GET = createjs.AbstractLoader.GET;
+ this._loadQueue = [];
-// events
/**
- * This event is fired when an individual file has loaded, and been processed.
- * @event fileload
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type.
- * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
- * object will contain that value as a `src` property.
- * @param {Object} result The HTML tag or parsed result of the loaded item.
- * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
- * to a usable object.
- * @since 0.3.0
+ * An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
+ * @property _loadQueueBackup
+ * @type {Array}
+ * @private
*/
+ this._loadQueueBackup = [];
/**
- * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
- * @event fileprogress
- * @since 0.3.0
+ * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}}
+ * id.
+ * @property _loadItemsById
+ * @type {Object}
+ * @private
*/
+ this._loadItemsById = {};
/**
- * This event is fired when an individual file starts to load.
- * @event filestart
- * @param {Object} The object that dispatched the event.
- * @param {String} type The event type.
- * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
- * object will contain that value as a property.
+ * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * source.
+ * @property _loadItemsBySrc
+ * @type {Object}
+ * @private
*/
+ this._loadItemsBySrc = {};
/**
- * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from
- * a LoadQueue instance.
- * @event initialize
+ * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @property _loadedResults
+ * @type {Object}
* @private
*/
+ this._loadedResults = {};
-// public methods
/**
- * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
- * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
- * once, and will be prepended to the list of available loaders.
- * @method registerLoader
- * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
- * @since 0.6.0
+ * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @property _loadedRawResults
+ * @type {Object}
+ * @private
*/
- p.registerLoader = function (loader) {
- if (!loader || !loader.canLoadItem) {
- throw new Error("loader is of an incorrect type.");
- } else if (this._availableLoaders.indexOf(loader) != -1) {
- throw new Error("loader already exists."); //LM: Maybe just silently fail here
- }
-
- this._availableLoaders.unshift(loader);
- };
+ this._loadedRawResults = {};
/**
- * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
- * unregistered, the default loaders will always be available.
- * @method unregisterLoader
- * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
+ * The number of items that have been requested. This helps manage an overall progress without knowing how large
+ * the files are before they are downloaded. This does not include items inside of loaders such as the
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _numItems
+ * @type {Number}
+ * @default 0
+ * @private
*/
- p.unregisterLoader = function (loader) {
- var idx = this._availableLoaders.indexOf(loader);
- if (idx != -1 && idx < this._defaultLoaderLength - 1) {
- this._availableLoaders.splice(idx, 1);
- }
- };
+ this._numItems = 0;
/**
- * @method setUseXHR
- * @param {Boolean} value The new useXHR value to set.
- * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
- * the provided value argument was true.
- * @since 0.3.0
- * @deprecated use the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property, or the
- * {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} method instead.
+ * The number of items that have completed loaded. This helps manage an overall progress without knowing how large
+ * the files are before they are downloaded.
+ * @property _numItemsLoaded
+ * @type {Number}
+ * @default 0
+ * @private
*/
- p.setUseXHR = function (value) {
- return this.setPreferXHR(value);
- };
+ this._numItemsLoaded = 0;
/**
- * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
- * fail, or be ignored depending on the browser's capabilities and the load type.
- * @method setPreferXHR
- * @param {Boolean} value
- * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
- * @since 0.6.0
+ * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right
+ * order.
+ * @property _scriptOrder
+ * @type {Array}
+ * @private
*/
- p.setPreferXHR = function (value) {
- // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
- //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
- this.preferXHR = (value != false && window.XMLHttpRequest != null);
- return this.preferXHR;
- };
+ this._scriptOrder = [];
/**
- * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
- * content, and allows the queue to be used again.
- * @method removeAll
- * @since 0.3.0
+ * A list of scripts that have been loaded. Items are added to this list as null
when they are
+ * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true
+ * once they are complete and have been dispatched.
+ * @property _loadedScripts
+ * @type {Array}
+ * @private
*/
- p.removeAll = function () {
- this.remove();
- };
+ this._loadedScripts = [];
/**
- * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
- * This also removes internal references to loaded item(s).
- *
- * Example
- *
- * queue.loadManifest([
- * {src:"test.png", id:"png"},
- * {src:"test.jpg", id:"jpg"},
- * {src:"test.mp3", id:"mp3"}
- * ]);
- * queue.remove("png"); // Single item by ID
- * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
- * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
- *
- * @method remove
- * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
- * items, or multiple items as arguments.
- * @since 0.3.0
+ * The last progress amount. This is used to suppress duplicate progress events.
+ * @property _lastProgress
+ * @type {Number}
+ * @private
+ * @since 0.6.0
*/
- p.remove = function (idsOrUrls) {
- var args = null;
-
- if (idsOrUrls && !Array.isArray(idsOrUrls)) {
- args = [idsOrUrls];
- } else if (idsOrUrls) {
- args = idsOrUrls;
- } else if (arguments.length > 0) {
- return;
- }
+ this._lastProgress = NaN;
- var itemsWereRemoved = false;
+};
- // Destroy everything
- if (!args) {
- this.close();
- for (var n in this._loadItemsById) {
- this._disposeItem(this._loadItemsById[n]);
- }
- this.init(this.preferXHR, this._basePath);
+// static properties
+/**
+ * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event is dispatched if the timeout is reached before any data is received.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000
+ * @static
+ * @since 0.4.1
+ * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
+ */
+s.loadTimeout = 8000;
- // Remove specific items
- } else {
- while (args.length) {
- var item = args.pop();
- var r = this.getResult(item);
+/**
+ * The time in milliseconds to assume a load has failed.
+ * @property LOAD_TIMEOUT
+ * @type {Number}
+ * @default 0
+ * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
+ */
+s.LOAD_TIMEOUT = 0;
- //Remove from the main load Queue
- for (i = this._loadQueue.length - 1; i >= 0; i--) {
- loadItem = this._loadQueue[i].getItem();
- if (loadItem.id == item || loadItem.src == item) {
- this._loadQueue.splice(i, 1)[0].cancel();
- break;
- }
- }
+// Preload Types
+/**
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
+ */
+s.BINARY = AbstractLoader.BINARY;
- //Remove from the backup queue
- for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
- loadItem = this._loadQueueBackup[i].getItem();
- if (loadItem.id == item || loadItem.src == item) {
- this._loadQueueBackup.splice(i, 1)[0].cancel();
- break;
- }
- }
+/**
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+s.CSS = AbstractLoader.CSS;
- if (r) {
- this._disposeItem(this.getItem(item));
- } else {
- for (var i = this._currentLoads.length - 1; i >= 0; i--) {
- var loadItem = this._currentLoads[i].getItem();
- if (loadItem.id == item || loadItem.src == item) {
- this._currentLoads.splice(i, 1)[0].cancel();
- itemsWereRemoved = true;
- break;
- }
- }
- }
- }
+/**
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
+ */
+s.IMAGE = AbstractLoader.IMAGE;
- // If this was called during a load, try to load the next item.
- if (itemsWereRemoved) {
- this._loadNext();
- }
- }
- };
+/**
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.JAVASCRIPT = AbstractLoader.JAVASCRIPT;
- /**
- * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
- * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
- * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
- * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
- * @method reset
- * @since 0.3.0
- */
- p.reset = function () {
- this.close();
- for (var n in this._loadItemsById) {
- this._disposeItem(this._loadItemsById[n]);
- }
+/**
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
+ */
+s.JSON = AbstractLoader.JSON;
- //Reset the queue to its start state
- var a = [];
- for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
- a.push(this._loadQueueBackup[i].getItem());
- }
+/**
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
+ */
+s.JSONP = AbstractLoader.JSONP;
- this.loadManifest(a, false);
- };
+/**
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.4.1
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
+ */
+s.MANIFEST = AbstractLoader.MANIFEST;
- /**
- * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
- * Currently, only one plugin can exist per type/extension.
- *
- * When a plugin is installed, a getPreloadHandlers()
method will be called on it. For more information
- * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
- * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
- *
- * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
- * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
- * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
- * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
- * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
- * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
- *
- * @method installPlugin
- * @param {Function} plugin The plugin class to install.
- */
- p.installPlugin = function (plugin) {
- if (plugin == null) {
- return;
- }
+/**
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.SOUND = AbstractLoader.SOUND;
- if (plugin.getPreloadHandlers != null) {
- this._plugins.push(plugin);
- var map = plugin.getPreloadHandlers();
- map.scope = plugin;
+/**
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
+ */
+s.VIDEO = AbstractLoader.VIDEO;
- if (map.types != null) {
- for (var i = 0, l = map.types.length; i < l; i++) {
- this._typeCallbacks[map.types[i]] = map;
- }
- }
+/**
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
+ */
+s.SVG = AbstractLoader.SVG;
- if (map.extensions != null) {
- for (i = 0, l = map.extensions.length; i < l; i++) {
- this._extensionCallbacks[map.extensions[i]] = map;
- }
- }
- }
- };
+/**
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
+ */
+s.TEXT = AbstractLoader.TEXT;
- /**
- * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
- * number of open connections, so any additional connections may remain in a pending state until the browser
- * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
- * is `true`, only one script is loaded at a time due to browser limitations.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.setMaxConnections(10); // Allow 10 concurrent loads
- *
- * @method setMaxConnections
- * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
- * is open at any time.
- */
- p.setMaxConnections = function (value) {
- this._maxConnections = value;
- if (!this._paused && this._loadQueue.length > 0) {
- this._loadNext();
- }
- };
+/**
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
+ */
+s.XML = AbstractLoader.XML;
- /**
- * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
- * method.
- *
- * Files are always appended to the current queue, so this method can be used multiple times to add files.
- * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
- * @method loadFile
- * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
- *
- * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
- * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
- * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
- * in the background.
- *
- * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
- * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
- * `true`, the queue will resume automatically.
- * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
- * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
- * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
- * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
- * constructor, or a `path` property in a manifest definition.
- */
- p.loadFile = function (file, loadNow, basePath) {
- if (file == null) {
- var event = new createjs.ErrorEvent("PRELOAD_NO_FILE");
- this._sendError(event);
- return;
- }
- this._addItem(file, null, basePath);
+/**
+ * @property POST
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
+ */
+s.POST = AbstractLoader.POST;
- if (loadNow !== false) {
- this.setPaused(false);
- } else {
- this.setPaused(true);
- }
- };
+/**
+ * @property GET
+ * @type {string}
+ * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
+ */
+s.GET = AbstractLoader.GET;
- /**
- * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
- * The files in the manifest are requested in the same order, but may complete in a different order if the max
- * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
- * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
- * default).
- *
- * Files are always appended to the current queue, so this method can be used multiple times to add files.
- * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
- * @method loadManifest
- * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
- * manifests:
- *
- * - A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
- * which defines the list of files to load, and can optionally contain a "path" property, which will be
- * prepended to each file in the list.
- * - An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
- * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
- * and can optionally contain a "path" property, which will be prepended to each file in the list.
- * - An object which contains a "manifest" property, which defines the list of files to load, and can
- * optionally contain a "path" property, which will be prepended to each file in the list.
- * - An Array of files to load.
- *
- *
- * Each "file" in a manifest can be either:
- *
- * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
- * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
- * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
- * in the background.
- *
- *
- * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
- * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
- * `true`, the queue will resume automatically.
- * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
- * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
- * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
- * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
- * constructor, or a `path` property in a manifest definition.
- */
- p.loadManifest = function (manifest, loadNow, basePath) {
- var fileList = null;
- var path = null;
-
- // Array-based list of items
- if (Array.isArray(manifest)) {
- if (manifest.length == 0) {
- var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");
- this._sendError(event);
- return;
- }
- fileList = manifest;
-
- // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
- } else if (typeof(manifest) === "string") {
- fileList = [
- {
- src: manifest,
- type: s.MANIFEST
- }
- ];
+// events
+/**
+ * This event is fired when an individual file has loaded, and been processed.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.3.0
+ */
- } else if (typeof(manifest) == "object") {
+/**
+ * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
+ * @event fileprogress
+ * @since 0.3.0
+ */
- // An object that defines a manifest path
- if (manifest.src !== undefined) {
- if (manifest.type == null) {
- manifest.type = s.MANIFEST;
- } else if (manifest.type != s.MANIFEST) {
- var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");
- this._sendError(event);
- }
- fileList = [manifest];
+/**
+ * This event is fired when an individual file starts to load.
+ * @event filestart
+ * @param {Object} The object that dispatched the event.
+ * @param {String} type The event type.
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a property.
+ */
- // An object that defines a manifest
- } else if (manifest.manifest !== undefined) {
- fileList = manifest.manifest;
- path = manifest.path;
- }
+/**
+ * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from
+ * a LoadQueue instance.
+ * @event initialize
+ * @private
+ */
- // Unsupported. This will throw an error.
- } else {
- var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");
- this._sendError(event);
- return;
- }
-
- for (var i = 0, l = fileList.length; i < l; i++) {
- this._addItem(fileList[i], path, basePath);
- }
+// public methods
+/**
+ * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
+ * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
+ * once, and will be prepended to the list of available loaders.
+ * @method registerLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
+ * @since 0.6.0
+ */
+p.registerLoader = function (loader) {
+ if (!loader || !loader.canLoadItem) {
+ throw new Error("loader is of an incorrect type.");
+ } else if (this._availableLoaders.indexOf(loader) != -1) {
+ throw new Error("loader already exists."); //LM: Maybe just silently fail here
+ }
- if (loadNow !== false) {
- this.setPaused(false);
- } else {
- this.setPaused(true);
- }
+ this._availableLoaders.unshift(loader);
+};
- };
+/**
+ * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
+ * unregistered, the default loaders will always be available.
+ * @method unregisterLoader
+ * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
+ */
+p.unregisterLoader = function (loader) {
+ var idx = this._availableLoaders.indexOf(loader);
+ if (idx != -1 && idx < this._defaultLoaderLength - 1) {
+ this._availableLoaders.splice(idx, 1);
+ }
+};
- /**
- * Start a LoadQueue that was created, but not automatically started.
- * @method load
- */
- p.load = function () {
- this.setPaused(false);
- };
+/**
+ * @method setUseXHR
+ * @param {Boolean} value The new useXHR value to set.
+ * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
+ * the provided value argument was true.
+ * @since 0.3.0
+ * @deprecated use the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property, or the
+ * {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} method instead.
+ */
+p.setUseXHR = function (value) {
+ return this.setPreferXHR(value);
+};
- /**
- * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
- * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
- * `basePath` will not be part of the ID.
- * @method getItem
- * @param {String} value The id
or src
of the load item.
- * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
- * event as the `item` parameter.
- */
- p.getItem = function (value) {
- return this._loadItemsById[value] || this._loadItemsBySrc[value];
- };
+/**
+ * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
+ * fail, or be ignored depending on the browser's capabilities and the load type.
+ * @method setPreferXHR
+ * @param {Boolean} value
+ * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
+ * @since 0.6.0
+ */
+p.setPreferXHR = function (value) {
+ // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
+ //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
+ this.preferXHR = (value != false && window.XMLHttpRequest != null);
+ return this.preferXHR;
+};
- /**
- * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
- * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
- * `basePath` will not be part of the ID.
- * @method getResult
- * @param {String} value The id
or src
of the load item.
- * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
- * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
- * returned instead.
- * @return {Object} A result object containing the content that was loaded, such as:
- *
- * - An image tag (<image />) for images
- * - A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML
- * DOM.
- * - A style tag for CSS (<style /> or <link >)
- * - Raw text for TEXT
- * - A formatted JavaScript object defined by JSON
- * - An XML document
- * - A binary arraybuffer loaded by XHR
- * - An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play
- * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
- * which can not be used to play audio back.
- *
- * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
- * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
- */
- p.getResult = function (value, rawResult) {
- var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
- if (item == null) {
- return null;
- }
- var id = item.id;
- if (rawResult && this._loadedRawResults[id]) {
- return this._loadedRawResults[id];
- }
- return this._loadedResults[id];
- };
+/**
+ * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
+ * content, and allows the queue to be used again.
+ * @method removeAll
+ * @since 0.3.0
+ */
+p.removeAll = function () {
+ this.remove();
+};
- /**
- * Generate an list of items loaded by this queue.
- * @method getItems
- * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
- * and failed load items will also be included.
- * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
- * result, and rawResult.
- * @since 0.6.0
- */
- p.getItems = function (loaded) {
- var arr = [];
- for (var n in this._loadItemsById) {
- var item = this._loadItemsById[n];
- var result = this.getResult(n);
- if (loaded === true && result == null) {
- continue;
- }
- arr.push({
- item: item,
- result: result,
- rawResult: this.getResult(n, true)
- });
- }
- return arr;
- };
+/**
+ * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
+ * This also removes internal references to loaded item(s).
+ *
+ * Example
+ *
+ * queue.loadManifest([
+ * {src:"test.png", id:"png"},
+ * {src:"test.jpg", id:"jpg"},
+ * {src:"test.mp3", id:"mp3"}
+ * ]);
+ * queue.remove("png"); // Single item by ID
+ * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
+ * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
+ *
+ * @method remove
+ * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
+ * items, or multiple items as arguments.
+ * @since 0.3.0
+ */
+p.remove = function (idsOrUrls) {
+ var args = null;
+
+ if (idsOrUrls && !Array.isArray(idsOrUrls)) {
+ args = [idsOrUrls];
+ } else if (idsOrUrls) {
+ args = idsOrUrls;
+ } else if (arguments.length > 0) {
+ return;
+ }
- /**
- * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
- * be processed when active loads complete. LoadQueues are not paused by default.
- *
- * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
- * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
- * argument is `false`.
- * @method setPaused
- * @param {Boolean} value Whether the queue should be paused or not.
- */
- p.setPaused = function (value) {
- this._paused = value;
- if (!this._paused) {
- this._loadNext();
- }
- };
+ var itemsWereRemoved = false;
- /**
- * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
- * starting to download. Note that currently any active loads will remain open, and events may be processed.
- *
- * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
- * @method close
- */
- p.close = function () {
- while (this._currentLoads.length) {
- this._currentLoads.pop().cancel();
+ // Destroy everything
+ if (!args) {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
}
- this._scriptOrder.length = 0;
- this._loadedScripts.length = 0;
- this.loadStartWasDispatched = false;
- this._itemCount = 0;
- this._lastProgress = NaN;
- };
-
-// protected methods
- /**
- * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
- * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
- * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
- * method.
- * @method _addItem
- * @param {String|Object} value The item to add to the queue.
- * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
- * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
- * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
- * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
- * version.
- * @private
- */
- p._addItem = function (value, path, basePath) {
- var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
- if (item == null) {
- return;
- } // Sometimes plugins or types should be skipped.
- var loader = this._createLoader(item);
- if (loader != null) {
- if ("plugins" in loader) {
- loader.plugins = this._plugins;
- }
- item._loader = loader;
- this._loadQueue.push(loader);
- this._loadQueueBackup.push(loader);
-
- this._numItems++;
- this._updateProgress();
-
- // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
- if ((this.maintainScriptOrder
- && item.type == createjs.LoadQueue.JAVASCRIPT
- //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
- )
- || item.maintainOrder === true) {
- this._scriptOrder.push(item);
- this._loadedScripts.push(null);
+ this.init(this.preferXHR, this._basePath);
+
+ // Remove specific items
+ } else {
+ while (args.length) {
+ var item = args.pop();
+ var r = this.getResult(item);
+
+ //Remove from the main load Queue
+ for (i = this._loadQueue.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueue[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueue.splice(i, 1)[0].cancel();
+ break;
+ }
}
- }
- };
-
- /**
- * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
- * item is determined by browser support, requirements based on the file type, and developer settings. For example,
- * XHR is only used for file types that support it in new browsers.
- *
- * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
- * alter the load item.
- * @method _createLoadItem
- * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
- * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
- * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
- * when it is added.
- * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to
- * the path argument.
- * @return {Object} The loader instance that will be used.
- * @private
- */
- p._createLoadItem = function (value, path, basePath) {
- var item = createjs.LoadItem.create(value);
- if (item == null) {
- return null;
- }
- var bp = ""; // Store the generated basePath
- var useBasePath = basePath || this._basePath;
-
- if (item.src instanceof Object) {
- if (!item.type) {
- return null;
- } // the the src is an object, type is required to pass off to plugin
- if (path) {
- bp = path;
- var pathMatch = createjs.RequestUtils.parseURI(path);
- // Also append basePath
- if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
- bp = useBasePath + bp;
+ //Remove from the backup queue
+ for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
+ loadItem = this._loadQueueBackup[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._loadQueueBackup.splice(i, 1)[0].cancel();
+ break;
}
- } else if (useBasePath != null) {
- bp = useBasePath;
- }
- } else {
- // Determine Extension, etc.
- var match = createjs.RequestUtils.parseURI(item.src);
- if (match.extension) {
- item.ext = match.extension;
- }
- if (item.type == null) {
- item.type = createjs.RequestUtils.getTypeByExtension(item.ext);
}
- // Inject path & basePath
- var autoId = item.src;
- if (!match.absolute && !match.relative) {
- if (path) {
- bp = path;
- var pathMatch = createjs.RequestUtils.parseURI(path);
- autoId = path + autoId;
- // Also append basePath
- if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
- bp = useBasePath + bp;
+ if (r) {
+ this._disposeItem(this.getItem(item));
+ } else {
+ for (var i = this._currentLoads.length - 1; i >= 0; i--) {
+ var loadItem = this._currentLoads[i].getItem();
+ if (loadItem.id == item || loadItem.src == item) {
+ this._currentLoads.splice(i, 1)[0].cancel();
+ itemsWereRemoved = true;
+ break;
}
- } else if (useBasePath != null) {
- bp = useBasePath;
}
}
- item.src = bp + item.src;
}
- item.path = bp;
- // If there's no id, set one now.
- if (item.id === undefined || item.id === null || item.id === "") {
- item.id = autoId;
+ // If this was called during a load, try to load the next item.
+ if (itemsWereRemoved) {
+ this._loadNext();
}
+ }
+};
+
+/**
+ * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
+ * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
+ * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
+ * @method reset
+ * @since 0.3.0
+ */
+p.reset = function () {
+ this.close();
+ for (var n in this._loadItemsById) {
+ this._disposeItem(this._loadItemsById[n]);
+ }
- // Give plugins a chance to modify the loadItem:
- var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
- if (customHandler) {
- // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
- var result = customHandler.callback.call(customHandler.scope, item, this);
+ //Reset the queue to its start state
+ var a = [];
+ for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
+ a.push(this._loadQueueBackup[i].getItem());
+ }
+
+ this.loadManifest(a, false);
+};
- // The plugin will handle the load, or has canceled it. Ignore it.
- if (result === false) {
- return null;
+/**
+ * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
+ * Currently, only one plugin can exist per type/extension.
+ *
+ * When a plugin is installed, a getPreloadHandlers()
method will be called on it. For more information
+ * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
+ * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
+ *
+ * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
+ * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
+ * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
+ * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
+ * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
+ * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
+ *
+ * @method installPlugin
+ * @param {Function} plugin The plugin class to install.
+ */
+p.installPlugin = function (plugin) {
+ if (plugin == null) {
+ return;
+ }
- // Load as normal:
- } else if (result === true) {
- // Do Nothing
+ if (plugin.getPreloadHandlers != null) {
+ this._plugins.push(plugin);
+ var map = plugin.getPreloadHandlers();
+ map.scope = plugin;
- // Result is a loader class:
- } else if (result != null) {
- item._loader = result;
+ if (map.types != null) {
+ for (var i = 0, l = map.types.length; i < l; i++) {
+ this._typeCallbacks[map.types[i]] = map;
}
+ }
- // Update the extension in case the type changed:
- match = createjs.RequestUtils.parseURI(item.src);
- if (match.extension != null) {
- item.ext = match.extension;
+ if (map.extensions != null) {
+ for (i = 0, l = map.extensions.length; i < l; i++) {
+ this._extensionCallbacks[map.extensions[i]] = map;
}
}
+ }
+};
- // Store the item for lookup. This also helps clean-up later.
- this._loadItemsById[item.id] = item;
- this._loadItemsBySrc[item.src] = item;
+/**
+ * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
+ * number of open connections, so any additional connections may remain in a pending state until the browser
+ * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
+ * is `true`, only one script is loaded at a time due to browser limitations.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.setMaxConnections(10); // Allow 10 concurrent loads
+ *
+ * @method setMaxConnections
+ * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
+ * is open at any time.
+ */
+p.setMaxConnections = function (value) {
+ this._maxConnections = value;
+ if (!this._paused && this._loadQueue.length > 0) {
+ this._loadNext();
+ }
+};
- if (item.crossOrigin == null) {
- item.crossOrigin = this._crossOrigin;
- }
+/**
+ * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method.
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadFile
+ * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+p.loadFile = function (file, loadNow, basePath) {
+ if (file == null) {
+ var event = new ErrorEvent("PRELOAD_NO_FILE");
+ this._sendError(event);
+ return;
+ }
+ this._addItem(file, null, basePath);
- return item;
- };
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+};
- /**
- * Create a loader for a load item.
- * @method _createLoader
- * @param {Object} item A formatted load item that can be used to generate a loader.
- * @return {AbstractLoader} A loader that can be used to load content.
- * @private
- */
- p._createLoader = function (item) {
- if (item._loader != null) { // A plugin already specified a loader
- return item._loader;
+/**
+ * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
+ * The files in the manifest are requested in the same order, but may complete in a different order if the max
+ * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
+ * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
+ * default).
+ *
+ * Files are always appended to the current queue, so this method can be used multiple times to add files.
+ * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
+ * @method loadManifest
+ * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
+ * manifests:
+ *
+ * - A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
+ * which defines the list of files to load, and can optionally contain a "path" property, which will be
+ * prepended to each file in the list.
+ * - An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
+ * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
+ * and can optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An object which contains a "manifest" property, which defines the list of files to load, and can
+ * optionally contain a "path" property, which will be prepended to each file in the list.
+ * - An Array of files to load.
+ *
+ *
+ * Each "file" in a manifest can be either:
+ *
+ * - A {{#crossLink "LoadItem"}}{{/crossLink}} instance
+ * - An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
+ * - OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
+ * in the background.
+ *
+ *
+ * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
+ * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
+ * `true`, the queue will resume automatically.
+ * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
+ * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
+ * its files will NOT use the basePath parameter. The basePath parameter is deprecated.
+ * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
+ * constructor, or a `path` property in a manifest definition.
+ */
+p.loadManifest = function (manifest, loadNow, basePath) {
+ var fileList = null;
+ var path = null;
+
+ // Array-based list of items
+ if (Array.isArray(manifest)) {
+ if (manifest.length == 0) {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_EMPTY");
+ this._sendError(event);
+ return;
}
+ fileList = manifest;
+
+ // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
+ } else if (typeof(manifest) === "string") {
+ fileList = [
+ {
+ src: manifest,
+ type: s.MANIFEST
+ }
+ ];
- // Initially, try and use the provided/supported XHR mode:
- var preferXHR = this.preferXHR;
+ } else if (typeof(manifest) == "object") {
- for (var i = 0; i < this._availableLoaders.length; i++) {
- var loader = this._availableLoaders[i];
- if (loader && loader.canLoadItem(item)) {
- return new loader(item, preferXHR);
+ // An object that defines a manifest path
+ if (manifest.src !== undefined) {
+ if (manifest.type == null) {
+ manifest.type = s.MANIFEST;
+ } else if (manifest.type != s.MANIFEST) {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_TYPE");
+ this._sendError(event);
}
+ fileList = [manifest];
+
+ // An object that defines a manifest
+ } else if (manifest.manifest !== undefined) {
+ fileList = manifest.manifest;
+ path = manifest.path;
}
- // TODO: Log error (requires createjs.log)
+ // Unsupported. This will throw an error.
+ } else {
+ var event = new ErrorEvent("PRELOAD_MANIFEST_NULL");
+ this._sendError(event);
+ return;
+ }
+
+ for (var i = 0, l = fileList.length; i < l; i++) {
+ this._addItem(fileList[i], path, basePath);
+ }
+
+ if (loadNow !== false) {
+ this.setPaused(false);
+ } else {
+ this.setPaused(true);
+ }
+
+};
+
+/**
+ * Start a LoadQueue that was created, but not automatically started.
+ * @method load
+ */
+p.load = function () {
+ this.setPaused(false);
+};
+
+/**
+ * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
+ * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getItem
+ * @param {String} value The id
or src
of the load item.
+ * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
+ * event as the `item` parameter.
+ */
+p.getItem = function (value) {
+ return this._loadItemsById[value] || this._loadItemsBySrc[value];
+};
+
+/**
+ * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
+ * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
+ * `basePath` will not be part of the ID.
+ * @method getResult
+ * @param {String} value The id
or src
of the load item.
+ * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML
+ * DOM.
+ * - A style tag for CSS (<style /> or <link >)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - A binary arraybuffer loaded by XHR
+ * - An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play
+ * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
+ * which can not be used to play audio back.
+ *
+ * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
+ * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+p.getResult = function (value, rawResult) {
+ var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
+ if (item == null) {
return null;
- };
+ }
+ var id = item.id;
+ if (rawResult && this._loadedRawResults[id]) {
+ return this._loadedRawResults[id];
+ }
+ return this._loadedResults[id];
+};
- /**
- * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
- * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
- * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
- * using tags, which have to be loaded one at a time to maintain load order.
- * @method _loadNext
- * @private
- */
- p._loadNext = function () {
- if (this._paused) {
- return;
+/**
+ * Generate an list of items loaded by this queue.
+ * @method getItems
+ * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
+ * and failed load items will also be included.
+ * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
+ * result, and rawResult.
+ * @since 0.6.0
+ */
+p.getItems = function (loaded) {
+ var arr = [];
+ for (var n in this._loadItemsById) {
+ var item = this._loadItemsById[n];
+ var result = this.getResult(n);
+ if (loaded === true && result == null) {
+ continue;
}
+ arr.push({
+ item: item,
+ result: result,
+ rawResult: this.getResult(n, true)
+ });
+ }
+ return arr;
+};
+
+/**
+ * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
+ * be processed when active loads complete. LoadQueues are not paused by default.
+ *
+ * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
+ * argument is `false`.
+ * @method setPaused
+ * @param {Boolean} value Whether the queue should be paused or not.
+ */
+p.setPaused = function (value) {
+ this._paused = value;
+ if (!this._paused) {
+ this._loadNext();
+ }
+};
+
+/**
+ * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
+ * starting to download. Note that currently any active loads will remain open, and events may be processed.
+ *
+ * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
+ * @method close
+ */
+p.close = function () {
+ while (this._currentLoads.length) {
+ this._currentLoads.pop().cancel();
+ }
+ this._scriptOrder.length = 0;
+ this._loadedScripts.length = 0;
+ this.loadStartWasDispatched = false;
+ this._itemCount = 0;
+ this._lastProgress = NaN;
+};
- // Only dispatch loadstart event when the first file is loaded.
- if (!this._loadStartWasDispatched) {
- this._sendLoadStart();
- this._loadStartWasDispatched = true;
+// protected methods
+/**
+ * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
+ * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
+ * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
+ * method.
+ * @method _addItem
+ * @param {String|Object} value The item to add to the queue.
+ * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
+ * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
+ * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
+ * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
+ * version.
+ * @private
+ */
+p._addItem = function (value, path, basePath) {
+ var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
+ if (item == null) {
+ return;
+ } // Sometimes plugins or types should be skipped.
+ var loader = this._createLoader(item);
+ if (loader != null) {
+ if ("plugins" in loader) {
+ loader.plugins = this._plugins;
}
+ item._loader = loader;
+ this._loadQueue.push(loader);
+ this._loadQueueBackup.push(loader);
- // The queue has completed.
- if (this._numItems == this._numItemsLoaded) {
- this.loaded = true;
- this._sendComplete();
+ this._numItems++;
+ this._updateProgress();
- // Load the next queue, if it has been defined.
- if (this.next && this.next.load) {
- this.next.load();
- }
- } else {
- this.loaded = false;
+ // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
+ if ((this.maintainScriptOrder
+ && item.type == LoadQueue.JAVASCRIPT
+ //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
+ )
+ || item.maintainOrder === true) {
+ this._scriptOrder.push(item);
+ this._loadedScripts.push(null);
}
+ }
+};
+
+/**
+ * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
+ * item is determined by browser support, requirements based on the file type, and developer settings. For example,
+ * XHR is only used for file types that support it in new browsers.
+ *
+ * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
+ * alter the load item.
+ * @method _createLoadItem
+ * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
+ * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
+ * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
+ * when it is added.
+ * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to
+ * the path argument.
+ * @return {Object} The loader instance that will be used.
+ * @private
+ */
+p._createLoadItem = function (value, path, basePath) {
+ var item = LoadItem.create(value);
+ if (item == null) {
+ return null;
+ }
- // Must iterate forwards to load in the right order.
- for (var i = 0; i < this._loadQueue.length; i++) {
- if (this._currentLoads.length >= this._maxConnections) {
- break;
+ var bp = ""; // Store the generated basePath
+ var useBasePath = basePath || this._basePath;
+
+ if (item.src instanceof Object) {
+ if (!item.type) {
+ return null;
+ } // the the src is an object, type is required to pass off to plugin
+ if (path) {
+ bp = path;
+ var pathMatch = RequestUtils.parseURI(path);
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
}
- var loader = this._loadQueue[i];
+ } else if (useBasePath != null) {
+ bp = useBasePath;
+ }
+ } else {
+ // Determine Extension, etc.
+ var match = RequestUtils.parseURI(item.src);
+ if (match.extension) {
+ item.ext = match.extension;
+ }
+ if (item.type == null) {
+ item.type = RequestUtils.getTypeByExtension(item.ext);
+ }
- // Determine if we should be only loading one tag-script at a time:
- // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
- if (!this._canStartLoad(loader)) {
- continue;
+ // Inject path & basePath
+ var autoId = item.src;
+ if (!match.absolute && !match.relative) {
+ if (path) {
+ bp = path;
+ var pathMatch = RequestUtils.parseURI(path);
+ autoId = path + autoId;
+ // Also append basePath
+ if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
+ bp = useBasePath + bp;
+ }
+ } else if (useBasePath != null) {
+ bp = useBasePath;
}
- this._loadQueue.splice(i, 1);
- i--;
- this._loadItem(loader);
}
- };
+ item.src = bp + item.src;
+ }
+ item.path = bp;
- /**
- * Begin loading an item. Event listeners are not added to the loaders until the load starts.
- * @method _loadItem
- * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
- * @private
- */
- p._loadItem = function (loader) {
- loader.on("fileload", this._handleFileLoad, this);
- loader.on("progress", this._handleProgress, this);
- loader.on("complete", this._handleFileComplete, this);
- loader.on("error", this._handleError, this);
- loader.on("fileerror", this._handleFileError, this);
- this._currentLoads.push(loader);
- this._sendFileStart(loader.getItem());
- loader.load();
- };
+ // If there's no id, set one now.
+ if (item.id === undefined || item.id === null || item.id === "") {
+ item.id = autoId;
+ }
- /**
- * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
- * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
- * events.
- * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
- * @private
- * @since 0.6.0
- */
- p._handleFileLoad = function (event) {
- event.target = null;
- this.dispatchEvent(event);
- };
+ // Give plugins a chance to modify the loadItem:
+ var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
+ if (customHandler) {
+ // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
+ var result = customHandler.callback.call(customHandler.scope, item, this);
- /**
- * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
- * loaders like M
- * @param event
- * @private
- */
- p._handleFileError = function (event) {
- var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item);
- this._sendError(newEvent);
- };
+ // The plugin will handle the load, or has canceled it. Ignore it.
+ if (result === false) {
+ return null;
- /**
- * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
- * is set to `true`.
- * @method _handleError
- * @param {ErrorEvent} event The error event, containing relevant error information.
- * @private
- */
- p._handleError = function (event) {
- var loader = event.target;
- this._numItemsLoaded++;
+ // Load as normal:
+ } else if (result === true) {
+ // Do Nothing
- this._finishOrderedItem(loader, true);
- this._updateProgress();
+ // Result is a loader class:
+ } else if (result != null) {
+ item._loader = result;
+ }
- var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
- // TODO: Propagate actual error message.
+ // Update the extension in case the type changed:
+ match = RequestUtils.parseURI(item.src);
+ if (match.extension != null) {
+ item.ext = match.extension;
+ }
+ }
- this._sendError(newEvent);
+ // Store the item for lookup. This also helps clean-up later.
+ this._loadItemsById[item.id] = item;
+ this._loadItemsBySrc[item.src] = item;
- if (!this.stopOnError) {
- this._removeLoadItem(loader);
- this._cleanLoadItem(loader);
- this._loadNext();
- } else {
- this.setPaused(true);
- }
- };
+ if (item.crossOrigin == null) {
+ item.crossOrigin = this._crossOrigin;
+ }
- /**
- * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
- * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
- * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
- * @method _handleFileComplete
- * @param {Event} event The event object from the loader.
- * @private
- */
- p._handleFileComplete = function (event) {
- var loader = event.target;
- var item = loader.getItem();
-
- var result = loader.getResult();
- this._loadedResults[item.id] = result;
- var rawResult = loader.getResult(true);
- if (rawResult != null && rawResult !== result) {
- this._loadedRawResults[item.id] = rawResult;
- }
+ return item;
+};
- this._saveLoadedItems(loader);
+/**
+ * Create a loader for a load item.
+ * @method _createLoader
+ * @param {Object} item A formatted load item that can be used to generate a loader.
+ * @return {AbstractLoader} A loader that can be used to load content.
+ * @private
+ */
+p._createLoader = function (item) {
+ if (item._loader != null) { // A plugin already specified a loader
+ return item._loader;
+ }
- // Remove the load item
- this._removeLoadItem(loader);
+ // Initially, try and use the provided/supported XHR mode:
+ var preferXHR = this.preferXHR;
- if (!this._finishOrderedItem(loader)) {
- // The item was NOT managed, so process it now
- this._processFinishedLoad(item, loader);
+ for (var i = 0; i < this._availableLoaders.length; i++) {
+ var loader = this._availableLoaders[i];
+ if (loader && loader.canLoadItem(item)) {
+ return new loader(item, preferXHR);
}
+ }
- // Clean up the load item
- this._cleanLoadItem(loader);
- };
+ // TODO: Log error (requires createjs.log)
+ return null;
+};
- /**
- * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
- * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
- * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
- * methods.
- * @method _saveLoadedItems
- * @param {AbstractLoader} loader
- * @protected
- * @since 0.6.0
- */
- p._saveLoadedItems = function (loader) {
- // TODO: Not sure how to handle this. Would be nice to expose the items.
- // Loaders may load sub-items. This adds them to this queue
- var list = loader.getLoadedItems();
- if (list === null) {
- return;
- }
+/**
+ * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
+ * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
+ * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
+ * using tags, which have to be loaded one at a time to maintain load order.
+ * @method _loadNext
+ * @private
+ */
+p._loadNext = function () {
+ if (this._paused) {
+ return;
+ }
- for (var i = 0; i < list.length; i++) {
- var item = list[i].item;
+ // Only dispatch loadstart event when the first file is loaded.
+ if (!this._loadStartWasDispatched) {
+ this._sendLoadStart();
+ this._loadStartWasDispatched = true;
+ }
- // Store item lookups
- this._loadItemsBySrc[item.src] = item;
- this._loadItemsById[item.id] = item;
+ // The queue has completed.
+ if (this._numItems == this._numItemsLoaded) {
+ this.loaded = true;
+ this._sendComplete();
- // Store loaded content
- this._loadedResults[item.id] = list[i].result;
- this._loadedRawResults[item.id] = list[i].rawResult;
+ // Load the next queue, if it has been defined.
+ if (this.next && this.next.load) {
+ this.next.load();
}
- };
+ } else {
+ this.loaded = false;
+ }
- /**
- * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
- * so, trigger prior items to trigger as well.
- * @method _finishOrderedItem
- * @param {AbstractLoader} loader
- * @param {Boolean} loadFailed
- * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
- * behaviour if it is.
- * @private
- */
- p._finishOrderedItem = function (loader, loadFailed) {
- var item = loader.getItem();
+ // Must iterate forwards to load in the right order.
+ for (var i = 0; i < this._loadQueue.length; i++) {
+ if (this._currentLoads.length >= this._maxConnections) {
+ break;
+ }
+ var loader = this._loadQueue[i];
- if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
- || item.maintainOrder) {
+ // Determine if we should be only loading one tag-script at a time:
+ // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
+ if (!this._canStartLoad(loader)) {
+ continue;
+ }
+ this._loadQueue.splice(i, 1);
+ i--;
+ this._loadItem(loader);
+ }
+};
- //TODO: Evaluate removal of the _currentlyLoadingScript
- if (loader instanceof createjs.JavaScriptLoader) {
- this._currentlyLoadingScript = false;
- }
+/**
+ * Begin loading an item. Event listeners are not added to the loaders until the load starts.
+ * @method _loadItem
+ * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
+ * @private
+ */
+p._loadItem = function (loader) {
+ loader.on("fileload", this._handleFileLoad, this);
+ loader.on("progress", this._handleProgress, this);
+ loader.on("complete", this._handleFileComplete, this);
+ loader.on("error", this._handleError, this);
+ loader.on("fileerror", this._handleFileError, this);
+ this._currentLoads.push(loader);
+ this._sendFileStart(loader.getItem());
+ loader.load();
+};
- var index = createjs.indexOf(this._scriptOrder, item);
- if (index == -1) {
- return false;
- } // This loader no longer exists
- this._loadedScripts[index] = (loadFailed === true) ? true : item;
+/**
+ * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
+ * events.
+ * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
+ * @private
+ * @since 0.6.0
+ */
+p._handleFileLoad = function (event) {
+ event.target = null;
+ this.dispatchEvent(event);
+};
- this._checkScriptLoadOrder();
- return true;
- }
+/**
+ * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
+ * loaders like M
+ * @param event
+ * @private
+ */
+p._handleFileError = function (event) {
+ var newEvent = new ErrorEvent("FILE_LOAD_ERROR", null, event.item);
+ this._sendError(newEvent);
+};
- return false;
- };
+/**
+ * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
+ * is set to `true`.
+ * @method _handleError
+ * @param {ErrorEvent} event The error event, containing relevant error information.
+ * @private
+ */
+p._handleError = function (event) {
+ var loader = event.target;
+ this._numItemsLoaded++;
- /**
- * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
- * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
- * and then when they are processed and dispatched, the value is set to `true`. This method simply
- * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
- * dispatched.
- * @method _checkScriptLoadOrder
- * @private
- */
- p._checkScriptLoadOrder = function () {
- var l = this._loadedScripts.length;
-
- for (var i = 0; i < l; i++) {
- var item = this._loadedScripts[i];
- if (item === null) {
- break;
- } // This is still loading. Do not process further.
- if (item === true) {
- continue;
- } // This has completed, and been processed. Move on.
-
- var loadItem = this._loadedResults[item.id];
- if (item.type == createjs.LoadQueue.JAVASCRIPT) {
- // Append script tags to the head automatically.
- createjs.DomUtils.appendToHead(loadItem);
- }
+ this._finishOrderedItem(loader, true);
+ this._updateProgress();
- var loader = item._loader;
- this._processFinishedLoad(item, loader);
- this._loadedScripts[i] = true;
- }
- };
+ var newEvent = new ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
+ // TODO: Propagate actual error message.
- /**
- * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
- * the next item.
- * @method _processFinishedLoad
- * @param {LoadItem|Object} item
- * @param {AbstractLoader} loader
- * @protected
- */
- p._processFinishedLoad = function (item, loader) {
- this._numItemsLoaded++;
-
- // Since LoadQueue needs maintain order, we can't append scripts in the loader.
- // So we do it here instead. Or in _checkScriptLoadOrder();
- if (!this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) {
- var tag = loader.getTag();
- createjs.DomUtils.appendToHead(tag);
- }
+ this._sendError(newEvent);
- this._updateProgress();
- this._sendFileComplete(item, loader);
+ if (!this.stopOnError) {
+ this._removeLoadItem(loader);
+ this._cleanLoadItem(loader);
this._loadNext();
- };
+ } else {
+ this.setPaused(true);
+ }
+};
- /**
- * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
- * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before
- * the script can even be started, since it exist in the DOM while loading.
- * @method _canStartLoad
- * @param {AbstractLoader} loader The loader for the item
- * @return {Boolean} Whether the item can start a load or not.
- * @private
- */
- p._canStartLoad = function (loader) {
- if (!this.maintainScriptOrder || loader.preferXHR) {
- return true;
- }
- var item = loader.getItem();
- if (item.type != createjs.LoadQueue.JAVASCRIPT) {
- return true;
+/**
+ * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
+ * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
+ * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
+ * @method _handleFileComplete
+ * @param {Event} event The event object from the loader.
+ * @private
+ */
+p._handleFileComplete = function (event) {
+ var loader = event.target;
+ var item = loader.getItem();
+
+ var result = loader.getResult();
+ this._loadedResults[item.id] = result;
+ var rawResult = loader.getResult(true);
+ if (rawResult != null && rawResult !== result) {
+ this._loadedRawResults[item.id] = rawResult;
+ }
+
+ this._saveLoadedItems(loader);
+
+ // Remove the load item
+ this._removeLoadItem(loader);
+
+ if (!this._finishOrderedItem(loader)) {
+ // The item was NOT managed, so process it now
+ this._processFinishedLoad(item, loader);
+ }
+
+ // Clean up the load item
+ this._cleanLoadItem(loader);
+};
+
+/**
+ * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
+ * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
+ * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
+ * methods.
+ * @method _saveLoadedItems
+ * @param {AbstractLoader} loader
+ * @protected
+ * @since 0.6.0
+ */
+p._saveLoadedItems = function (loader) {
+ // TODO: Not sure how to handle this. Would be nice to expose the items.
+ // Loaders may load sub-items. This adds them to this queue
+ var list = loader.getLoadedItems();
+ if (list === null) {
+ return;
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i].item;
+
+ // Store item lookups
+ this._loadItemsBySrc[item.src] = item;
+ this._loadItemsById[item.id] = item;
+
+ // Store loaded content
+ this._loadedResults[item.id] = list[i].result;
+ this._loadedRawResults[item.id] = list[i].rawResult;
+ }
+};
+
+/**
+ * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
+ * so, trigger prior items to trigger as well.
+ * @method _finishOrderedItem
+ * @param {AbstractLoader} loader
+ * @param {Boolean} loadFailed
+ * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
+ * behaviour if it is.
+ * @private
+ */
+p._finishOrderedItem = function (loader, loadFailed) {
+ var item = loader.getItem();
+
+ if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
+ || item.maintainOrder) {
+
+ //TODO: Evaluate removal of the _currentlyLoadingScript
+ if (loader instanceof createjs.JavaScriptLoader) {
+ this._currentlyLoadingScript = false;
}
- if (this._currentlyLoadingScript) {
+
+ var index = createjs.indexOf(this._scriptOrder, item);
+ if (index == -1) {
return false;
- }
+ } // This loader no longer exists
+ this._loadedScripts[index] = (loadFailed === true) ? true : item;
- var index = this._scriptOrder.indexOf(item);
- var i = 0;
- while (i < index) {
- var checkItem = this._loadedScripts[i];
- if (checkItem == null) {
- return false;
- }
- i++;
- }
- this._currentlyLoadingScript = true;
+ this._checkScriptLoadOrder();
return true;
- };
+ }
- /**
- * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
- * @method _removeLoadItem
- * @param {AbstractLoader} loader A loader instance to remove.
- * @private
- */
- p._removeLoadItem = function (loader) {
- var l = this._currentLoads.length;
- for (var i = 0; i < l; i++) {
- if (this._currentLoads[i] == loader) {
- this._currentLoads.splice(i, 1);
- break;
- }
- }
- };
+ return false;
+};
- /**
- * Remove unneeded references from a loader.
- *
- * @param loader
- * @private
- */
- p._cleanLoadItem = function(loader) {
- var item = loader.getItem();
- if (item) {
- delete item._loader;
+/**
+ * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
+ * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
+ * and then when they are processed and dispatched, the value is set to `true`. This method simply
+ * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
+ * dispatched.
+ * @method _checkScriptLoadOrder
+ * @private
+ */
+p._checkScriptLoadOrder = function () {
+ var l = this._loadedScripts.length;
+
+ for (var i = 0; i < l; i++) {
+ var item = this._loadedScripts[i];
+ if (item === null) {
+ break;
+ } // This is still loading. Do not process further.
+ if (item === true) {
+ continue;
+ } // This has completed, and been processed. Move on.
+
+ var loadItem = this._loadedResults[item.id];
+ if (item.type == createjs.LoadQueue.JAVASCRIPT) {
+ // Append script tags to the head automatically.
+ createjs.DomUtils.appendToHead(loadItem);
}
+
+ var loader = item._loader;
+ this._processFinishedLoad(item, loader);
+ this._loadedScripts[i] = true;
}
+};
- /**
- * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
- * @method _handleProgress
- * @param {ProgressEvent} event The progress event from the item.
- * @private
- */
- p._handleProgress = function (event) {
- var loader = event.target;
- this._sendFileProgress(loader.getItem(), loader.progress);
- this._updateProgress();
- };
+/**
+ * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
+ * the next item.
+ * @method _processFinishedLoad
+ * @param {LoadItem|Object} item
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+p._processFinishedLoad = function (item, loader) {
+ this._numItemsLoaded++;
+
+ // Since LoadQueue needs maintain order, we can't append scripts in the loader.
+ // So we do it here instead. Or in _checkScriptLoadOrder();
+ if (!this.maintainScriptOrder && item.type == LoadQueue.JAVASCRIPT) {
+ var tag = loader.getTag();
+ createjs.DomUtils.appendToHead(tag);
+ }
- /**
- * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
- * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
- * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
- * loaded progress on top of the already-loaded items.
- *
- * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
- *
- * - 5/10 of the items in the queue (50%)
- * - plus 20% of item 6's slot (2%)
- * - equals 52%
- *
- * @method _updateProgress
- * @private
- */
- p._updateProgress = function () {
- var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
- var remaining = this._numItems - this._numItemsLoaded;
- if (remaining > 0) {
- var chunk = 0;
- for (var i = 0, l = this._currentLoads.length; i < l; i++) {
- chunk += this._currentLoads[i].progress;
- }
- loaded += (chunk / remaining) * (remaining / this._numItems);
+ this._updateProgress();
+ this._sendFileComplete(item, loader);
+ this._loadNext();
+};
+
+/**
+ * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
+ * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before
+ * the script can even be started, since it exist in the DOM while loading.
+ * @method _canStartLoad
+ * @param {AbstractLoader} loader The loader for the item
+ * @return {Boolean} Whether the item can start a load or not.
+ * @private
+ */
+p._canStartLoad = function (loader) {
+ if (!this.maintainScriptOrder || loader.preferXHR) {
+ return true;
+ }
+ var item = loader.getItem();
+ if (item.type != LoadQueue.JAVASCRIPT) {
+ return true;
+ }
+ if (this._currentlyLoadingScript) {
+ return false;
+ }
+
+ var index = this._scriptOrder.indexOf(item);
+ var i = 0;
+ while (i < index) {
+ var checkItem = this._loadedScripts[i];
+ if (checkItem == null) {
+ return false;
}
+ i++;
+ }
+ this._currentlyLoadingScript = true;
+ return true;
+};
- if (this._lastProgress != loaded) {
- this._sendProgress(loaded);
- this._lastProgress = loaded;
+/**
+ * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
+ * @method _removeLoadItem
+ * @param {AbstractLoader} loader A loader instance to remove.
+ * @private
+ */
+p._removeLoadItem = function (loader) {
+ var l = this._currentLoads.length;
+ for (var i = 0; i < l; i++) {
+ if (this._currentLoads[i] == loader) {
+ this._currentLoads.splice(i, 1);
+ break;
}
- };
+ }
+};
- /**
- * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
- * hashes.
- * @method _disposeItem
- * @param {LoadItem|Object} item The item that was passed in for preloading.
- * @private
- */
- p._disposeItem = function (item) {
- delete this._loadedResults[item.id];
- delete this._loadedRawResults[item.id];
- delete this._loadItemsById[item.id];
- delete this._loadItemsBySrc[item.src];
- };
+/**
+ * Remove unneeded references from a loader.
+ *
+ * @param loader
+ * @private
+ */
+p._cleanLoadItem = function (loader) {
+ var item = loader.getItem();
+ if (item) {
+ delete item._loader;
+ }
+}
- /**
- * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
- * event for details on the event payload.
- * @method _sendFileProgress
- * @param {LoadItem|Object} item The item that is being loaded.
- * @param {Number} progress The amount the item has been loaded (between 0 and 1).
- * @protected
- */
- p._sendFileProgress = function (item, progress) {
- if (this._isCanceled() || this._paused) {
- return;
- }
- if (!this.hasEventListener("fileprogress")) {
- return;
+/**
+ * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
+ * @method _handleProgress
+ * @param {ProgressEvent} event The progress event from the item.
+ * @private
+ */
+p._handleProgress = function (event) {
+ var loader = event.target;
+ this._sendFileProgress(loader.getItem(), loader.progress);
+ this._updateProgress();
+};
+
+/**
+ * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
+ * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
+ * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
+ * loaded progress on top of the already-loaded items.
+ *
+ * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
+ *
+ * - 5/10 of the items in the queue (50%)
+ * - plus 20% of item 6's slot (2%)
+ * - equals 52%
+ *
+ * @method _updateProgress
+ * @private
+ */
+p._updateProgress = function () {
+ var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
+ var remaining = this._numItems - this._numItemsLoaded;
+ if (remaining > 0) {
+ var chunk = 0;
+ for (var i = 0, l = this._currentLoads.length; i < l; i++) {
+ chunk += this._currentLoads[i].progress;
}
+ loaded += (chunk / remaining) * (remaining / this._numItems);
+ }
- //LM: Rework ProgressEvent to support this?
- var event = new createjs.Event("fileprogress");
- event.progress = progress;
- event.loaded = progress;
- event.total = 1;
- event.item = item;
+ if (this._lastProgress != loaded) {
+ this._sendProgress(loaded);
+ this._lastProgress = loaded;
+ }
+};
- this.dispatchEvent(event);
- };
+/**
+ * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
+ * hashes.
+ * @method _disposeItem
+ * @param {LoadItem|Object} item The item that was passed in for preloading.
+ * @private
+ */
+p._disposeItem = function (item) {
+ delete this._loadedResults[item.id];
+ delete this._loadedRawResults[item.id];
+ delete this._loadItemsById[item.id];
+ delete this._loadItemsBySrc[item.src];
+};
- /**
- * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
- * details on the event payload.
- * @method _sendFileComplete
- * @param {LoadItemObject} item The item that is being loaded.
- * @param {AbstractLoader} loader
- * @protected
- */
- p._sendFileComplete = function (item, loader) {
- if (this._isCanceled() || this._paused) {
- return;
- }
+/**
+ * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendFileProgress
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @param {Number} progress The amount the item has been loaded (between 0 and 1).
+ * @protected
+ */
+p._sendFileProgress = function (item, progress) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
+ if (!this.hasEventListener("fileprogress")) {
+ return;
+ }
- var event = new createjs.Event("fileload");
- event.loader = loader;
- event.item = item;
- event.result = this._loadedResults[item.id];
- event.rawResult = this._loadedRawResults[item.id];
+ //LM: Rework ProgressEvent to support this?
+ var event = new Event("fileprogress");
+ event.progress = progress;
+ event.loaded = progress;
+ event.total = 1;
+ event.item = item;
- // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
- if (item.completeHandler) {
- item.completeHandler(event);
- }
+ this.dispatchEvent(event);
+};
- this.hasEventListener("fileload") && this.dispatchEvent(event);
- };
+/**
+ * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
+ * details on the event payload.
+ * @method _sendFileComplete
+ * @param {LoadItemObject} item The item that is being loaded.
+ * @param {AbstractLoader} loader
+ * @protected
+ */
+p._sendFileComplete = function (item, loader) {
+ if (this._isCanceled() || this._paused) {
+ return;
+ }
- /**
- * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
- * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
- * @method _sendFileStart
- * @param {LoadItem|Object} item The item that is being loaded.
- * @protected
- */
- p._sendFileStart = function (item) {
- var event = new createjs.Event("filestart");
- event.item = item;
- this.hasEventListener("filestart") && this.dispatchEvent(event);
- };
-
- p.toString = function () {
- return "[PreloadJS LoadQueue]";
- };
-
- createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader");
-}());
+ var event = new Event("fileload");
+ event.loader = loader;
+ event.item = item;
+ event.result = this._loadedResults[item.id];
+ event.rawResult = this._loadedRawResults[item.id];
+
+ // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
+ if (item.completeHandler) {
+ item.completeHandler(event);
+ }
+
+ this.hasEventListener("fileload") && this.dispatchEvent(event);
+};
+
+/**
+ * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
+ * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
+ * @method _sendFileStart
+ * @param {LoadItem|Object} item The item that is being loaded.
+ * @protected
+ */
+p._sendFileStart = function (item) {
+ var event = new Event("filestart");
+ event.item = item;
+ this.hasEventListener("filestart") && this.dispatchEvent(event);
+};
+
+p.toString = function () {
+ return "[PreloadJS LoadQueue]";
+};
+
+var LoadQueue = promote(LoadQueue, "AbstractLoader");
+
+module.exports = LoadQueue;
\ No newline at end of file
diff --git a/src/preloadjs/PreloadJS.js b/src/preloadjs/PreloadJS.js
new file mode 100644
index 0000000..6767932
--- /dev/null
+++ b/src/preloadjs/PreloadJS.js
@@ -0,0 +1,16 @@
+// File for legacy window.createjs support.
+(function (name, definition) {
+ if (typeof module != 'undefined') module.exports = definition();
+ else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
+ else this[name] = definition();
+}('createjs', function () {
+ // TODO Merge in other libraries.
+ return {
+ LoadQueue: require("./LoadQueue"),
+ promote: require('../createjs/utils/promote'),
+ extend: require('../createjs/utils/extend'),
+ Event: require('../createjs/events/Event'),
+ ErrorEvent: require('../createjs/events/ErrorEvent'),
+ ProgressEvent: require('./events/ProgressEvent')
+ };
+}));
diff --git a/src/preloadjs/data/LoadItem.js b/src/preloadjs/data/LoadItem.js
index 8d7e9e0..66fe4fa 100644
--- a/src/preloadjs/data/LoadItem.js
+++ b/src/preloadjs/data/LoadItem.js
@@ -32,197 +32,194 @@
*/
// namespace:
-this.createjs = this.createjs || {};
-(function () {
- "use strict";
+/**
+ * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead,
+ * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A
+ * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the
+ * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}}
+ * @class LoadItem
+ * @constructor
+ * @since 0.6.0
+ */
+function LoadItem() {
+ /**
+ * The source of the file that is being loaded. This property is required. The source can either be a
+ * string (recommended), or an HTML tag.
+ * This can also be an object, but in that case it has to include a type and be handled by a plugin.
+ * @property src
+ * @type {String}
+ * @default null
+ */
+ this.src = null;
/**
- * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead,
- * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A
- * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the
- * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}}
- * @class LoadItem
- * @constructor
- * @since 0.6.0
+ * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
+ * be set manually. This is helpful in cases where a file does not have an extension.
+ * @property type
+ * @type {String}
+ * @default null
*/
- function LoadItem() {
- /**
- * The source of the file that is being loaded. This property is required. The source can either be a
- * string (recommended), or an HTML tag.
- * This can also be an object, but in that case it has to include a type and be handled by a plugin.
- * @property src
- * @type {String}
- * @default null
- */
- this.src = null;
-
- /**
- * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
- * be set manually. This is helpful in cases where a file does not have an extension.
- * @property type
- * @type {String}
- * @default null
- */
- this.type = null;
-
- /**
- * A string identifier which can be used to reference the loaded object. If none is provided, this will be
- * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
- * @property id
- * @type {String}
- * @default null
- */
- this.id = null;
-
- /**
- * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
- * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
- * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
- * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
- * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
- * @property maintainOrder
- * @type {Boolean}
- * @default false
- */
- this.maintainOrder = false;
-
- /**
- * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
- * @property callback
- * @type {String}
- * @default null
- */
- this.callback = null;
-
- /**
- * An arbitrary data object, which is included with the loaded object.
- * @property data
- * @type {Object}
- * @default null
- */
- this.data = null;
-
- /**
- * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
- * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
- * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
- * @property method
- * @type {String}
- * @default get
- */
- this.method = createjs.LoadItem.GET;
-
- /**
- * An object hash of name/value pairs to send to the server.
- * @property values
- * @type {Object}
- * @default null
- */
- this.values = null;
-
- /**
- * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
- * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
- * default headers by including them in your headers object.
- * @property headers
- * @type {Object}
- * @default null
- */
- this.headers = null;
-
- /**
- * Enable credentials for XHR requests.
- * @property withCredentials
- * @type {Boolean}
- * @default false
- */
- this.withCredentials = false;
-
- /**
- * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
- * based files (json, xml, text, css, js).
- * @property mimeType
- * @type {String}
- * @default null
- */
- this.mimeType = null;
-
- /**
- * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
- * @property crossOrigin
- * @type {boolean}
- * @default Anonymous
- */
- this.crossOrigin = null;
-
- /**
- * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
- * (level one) loading, as XHR (level 2) provides its own timeout event.
- * @property loadTimeout
- * @type {Number}
- * @default 8000 (8 seconds)
- */
- this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
- };
-
- var p = LoadItem.prototype = {};
- var s = LoadItem;
+ this.type = null;
/**
- * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
- * (level one) loading, as XHR (level 2) provides its own timeout event.
- * @property LOAD_TIMEOUT_DEFAULT
- * @type {number}
- * @static
+ * A string identifier which can be used to reference the loaded object. If none is provided, this will be
+ * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
+ * @property id
+ * @type {String}
+ * @default null
*/
- s.LOAD_TIMEOUT_DEFAULT = 8000;
+ this.id = null;
/**
- * Create a LoadItem.
- *
- * - String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
- * - LoadItem instances are returned as-is
- * - Objects are returned with any needed properties added
- *
- * @method create
- * @param {LoadItem|String|Object} value The load item value
- * @returns {LoadItem|Object}
- * @static
+ * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
+ * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
+ * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
+ * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
+ * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
+ * @property maintainOrder
+ * @type {Boolean}
+ * @default false
*/
- s.create = function (value) {
- if (typeof value == "string") {
- var item = new LoadItem();
- item.src = value;
- return item;
- } else if (value instanceof s) {
- return value;
- } else if (value instanceof Object && value.src) {
- if (value.loadTimeout == null) {
- value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
- }
- return value;
- } else {
- throw new Error("Type not recognized.");
- }
- };
+ this.maintainOrder = false;
+
+ /**
+ * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
+ * @property callback
+ * @type {String}
+ * @default null
+ */
+ this.callback = null;
+
+ /**
+ * An arbitrary data object, which is included with the loaded object.
+ * @property data
+ * @type {Object}
+ * @default null
+ */
+ this.data = null;
+
+ /**
+ * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
+ * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
+ * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @property method
+ * @type {String}
+ * @default get
+ */
+ this.method = LoadItem.GET;
+
+ /**
+ * An object hash of name/value pairs to send to the server.
+ * @property values
+ * @type {Object}
+ * @default null
+ */
+ this.values = null;
+
+ /**
+ * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
+ * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
+ * default headers by including them in your headers object.
+ * @property headers
+ * @type {Object}
+ * @default null
+ */
+ this.headers = null;
+
+ /**
+ * Enable credentials for XHR requests.
+ * @property withCredentials
+ * @type {Boolean}
+ * @default false
+ */
+ this.withCredentials = false;
+
+ /**
+ * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
+ * based files (json, xml, text, css, js).
+ * @property mimeType
+ * @type {String}
+ * @default null
+ */
+ this.mimeType = null;
+
+ /**
+ * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
+ * @property crossOrigin
+ * @type {boolean}
+ * @default Anonymous
+ */
+ this.crossOrigin = null;
/**
- * Provides a chainable shortcut method for setting a number of properties on the instance.
- *
- * Example
- *
- * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
- *
- * @method set
- * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
- * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
- */
- p.set = function(props) {
- for (var n in props) { this[n] = props[n]; }
- return this;
- };
-
- createjs.LoadItem = s;
-
-}());
+ * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property loadTimeout
+ * @type {Number}
+ * @default 8000 (8 seconds)
+ */
+ this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+};
+
+var p = LoadItem.prototype = {};
+var s = LoadItem;
+
+/**
+ * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
+ * (level one) loading, as XHR (level 2) provides its own timeout event.
+ * @property LOAD_TIMEOUT_DEFAULT
+ * @type {number}
+ * @static
+ */
+s.LOAD_TIMEOUT_DEFAULT = 8000;
+
+/**
+ * Create a LoadItem.
+ *
+ * - String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
+ * - LoadItem instances are returned as-is
+ * - Objects are returned with any needed properties added
+ *
+ * @method create
+ * @param {LoadItem|String|Object} value The load item value
+ * @returns {LoadItem|Object}
+ * @static
+ */
+s.create = function (value) {
+ if (typeof value == "string") {
+ var item = new LoadItem();
+ item.src = value;
+ return item;
+ } else if (value instanceof s) {
+ return value;
+ } else if (value instanceof Object && value.src) {
+ if (value.loadTimeout == null) {
+ value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
+ }
+ return value;
+ } else {
+ throw new Error("Type not recognized.");
+ }
+};
+
+/**
+ * Provides a chainable shortcut method for setting a number of properties on the instance.
+ *
+ * Example
+ *
+ * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
+ *
+ * @method set
+ * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
+ * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
+ */
+p.set = function (props) {
+ for (var n in props) {
+ this[n] = props[n];
+ }
+ return this;
+};
+
+var LoadItem = s;
+module.exports = LoadItem;
diff --git a/src/preloadjs/events/ProgressEvent.js b/src/preloadjs/events/ProgressEvent.js
index 69f61f8..d05c68f 100644
--- a/src/preloadjs/events/ProgressEvent.js
+++ b/src/preloadjs/events/ProgressEvent.js
@@ -31,60 +31,57 @@
* @module PreloadJS
*/
-// namespace:
-this.createjs = this.createjs || {};
+var promote = require('../../createjs/utils/promote');
+var extend = require('../../createjs/utils/extend');
+var Event = require('../../createjs/events/Event');
-(function (scope) {
- "use strict";
+// constructor
+/**
+ * A CreateJS {{#crossLink "Event"}}{{/crossLink}} that is dispatched when progress changes.
+ * @class ProgressEvent
+ * @param {Number} loaded The amount that has been loaded. This can be any number relative to the total.
+ * @param {Number} [total=1] The total amount that will load. This will default to 1, so if the `loaded` value is
+ * a percentage (between 0 and 1), it can be omitted.
+ * @todo Consider having this event be a "fileprogress" event as well
+ * @constructor
+ */
+function ProgressEvent(loaded, total) {
+ this.Event_constructor("progress");
- // constructor
/**
- * A CreateJS {{#crossLink "Event"}}{{/crossLink}} that is dispatched when progress changes.
- * @class ProgressEvent
- * @param {Number} loaded The amount that has been loaded. This can be any number relative to the total.
- * @param {Number} [total=1] The total amount that will load. This will default to 1, so if the `loaded` value is
- * a percentage (between 0 and 1), it can be omitted.
- * @todo Consider having this event be a "fileprogress" event as well
- * @constructor
+ * The amount that has been loaded (out of a total amount)
+ * @property loaded
+ * @type {Number}
*/
- function ProgressEvent(loaded, total) {
- this.Event_constructor("progress");
-
- /**
- * The amount that has been loaded (out of a total amount)
- * @property loaded
- * @type {Number}
- */
- this.loaded = loaded;
-
- /**
- * The total "size" of the load.
- * @property total
- * @type {Number}
- * @default 1
- */
- this.total = (total == null) ? 1 : total;
-
- /**
- * The percentage (out of 1) that the load has been completed. This is calculated using `loaded/total`.
- * @property progress
- * @type {Number}
- * @default 0
- */
- this.progress = (total == 0) ? 0 : this.loaded / this.total;
- };
+ this.loaded = loaded;
- var p = createjs.extend(ProgressEvent, createjs.Event);
+ /**
+ * The total "size" of the load.
+ * @property total
+ * @type {Number}
+ * @default 1
+ */
+ this.total = (total == null) ? 1 : total;
/**
- * Returns a clone of the ProgressEvent instance.
- * @method clone
- * @return {ProgressEvent} a clone of the Event instance.
- **/
- p.clone = function() {
- return new createjs.ProgressEvent(this.loaded, this.total);
- };
+ * The percentage (out of 1) that the load has been completed. This is calculated using `loaded/total`.
+ * @property progress
+ * @type {Number}
+ * @default 0
+ */
+ this.progress = (total == 0) ? 0 : this.loaded / this.total;
+};
- createjs.ProgressEvent = createjs.promote(ProgressEvent, "Event");
+var p = extend(ProgressEvent, Event);
+
+/**
+ * Returns a clone of the ProgressEvent instance.
+ * @method clone
+ * @return {ProgressEvent} a clone of the Event instance.
+ **/
+p.clone = function () {
+ return new ProgressEvent(this.loaded, this.total);
+};
-}(window));
\ No newline at end of file
+var ProgressEvent = promote(ProgressEvent, "Event");
+module.exports = ProgressEvent;
diff --git a/src/preloadjs/loaders/AbstractLoader.js b/src/preloadjs/loaders/AbstractLoader.js
index 8d43d19..1e1cbdb 100644
--- a/src/preloadjs/loaders/AbstractLoader.js
+++ b/src/preloadjs/loaders/AbstractLoader.js
@@ -31,729 +31,746 @@
* @module PreloadJS
*/
-// namespace:
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
+var EventDispatcher = require('../../createjs/events/EventDispatcher');
+var LoadItem = require('../data/LoadItem');
+var Event = require('../../createjs/events/Event');
+var ErrorEvent = require('../../createjs/events/ErrorEvent');
+var ProgressEvent = require('../events/ProgressEvent');
+var RequestUtils = require('../utils/RequestUtils');
+var TagRequest = require('../net/TagRequest');
+var XHRRequest = require('../net/XHRRequest');
+var proxy = require('../../createjs/utils/proxy');
+var promote = require('../../createjs/utils/promote');
+var extend = require('../../createjs/utils/extend');
+// namespace:
// constructor
- /**
- * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
- * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
- * @class AbstractLoader
- * @param {LoadItem|object|string} loadItem The item to be loaded.
- * @param {Boolean} [preferXHR] Determines if the LoadItem should try and load using XHR, or take a
- * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
- * other, so this is a suggested directive.
- * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
- * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
- * @extends EventDispatcher
- */
- function AbstractLoader(loadItem, preferXHR, type) {
- this.EventDispatcher_constructor();
-
- // public properties
- /**
- * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
- * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
- * @property loaded
- * @type {Boolean}
- * @default false
- */
- this.loaded = false;
-
- /**
- * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
- * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
- * instead.
- * @property canceled
- * @type {Boolean}
- * @default false
- * @readonly
- */
- this.canceled = false;
-
- /**
- * The current load progress (percentage) for this item. This will be a number between 0 and 1.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.loadFile("largeImage.png");
- * queue.on("progress", function() {
- * console.log("Progress:", queue.progress, event.progress);
- * });
- *
- * @property progress
- * @type {Number}
- * @default 0
- */
- this.progress = 0;
-
- /**
- * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
- * supported types.
- * @property type
- * @type {String}
- */
- this.type = type;
-
- /**
- * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
- * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
- * can be overridden to provide custom formatting.
- *
- * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
- * asynchronous, such as creating a new image. The callback function is passed 2 parameters, which are callbacks
- * to handle success and error conditions in the resultFormatter. Note that the resultFormatter method is
- * called in the current scope, as well as the success and error callbacks.
- *
- * Example asynchronous resultFormatter
- *
- * function _formatResult(loader) {
- * return function(success, error) {
- * if (errorCondition) { error(errorDetailEvent); }
- * success(result);
- * }
- * }
- * @property resultFormatter
- * @type {Function}
- * @default null
- */
- this.resultFormatter = null;
-
- // protected properties
- /**
- * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
- * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
- * @property _item
- * @type {LoadItem|Object}
- * @private
- */
- if (loadItem) {
- this._item = createjs.LoadItem.create(loadItem);
- } else {
- this._item = null;
- }
-
- /**
- * Whether the loader will try and load content using XHR (true) or HTML tags (false).
- * @property _preferXHR
- * @type {Boolean}
- * @private
- */
- this._preferXHR = preferXHR;
-
- /**
- * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
- * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
- * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
- * @property _result
- * @type {Object|String}
- * @private
- */
- this._result = null;
-
- /**
- * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
- * method, and passing `true`.
- * @property _rawResult
- * @type {Object|String}
- * @private
- */
- this._rawResult = null;
-
- /**
- * A list of items that loaders load behind the scenes. This does not include the main item the loader is
- * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
- * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
- * @property _loadItems
- * @type {null}
- * @protected
- */
- this._loadedItems = null;
-
- /**
- * The attribute the items loaded using tags use for the source.
- * @type {string}
- * @default null
- * @private
- */
- this._tagSrcAttribute = null;
-
- /**
- * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
- * @property _tag
- * @type {Object}
- * @private
- */
- this._tag = null;
- };
-
- var p = createjs.extend(AbstractLoader, createjs.EventDispatcher);
- var s = AbstractLoader;
-
- // TODO: deprecated
- // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
-
-
- /**
- * Defines a POST request, use for a method value when loading data.
- * @property POST
- * @type {string}
- * @default post
- * @static
- */
- s.POST = "POST";
+/**
+ * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
+ * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
+ * @class AbstractLoader
+ * @param {LoadItem|object|string} loadItem The item to be loaded.
+ * @param {Boolean} [preferXHR] Determines if the LoadItem should try and load using XHR, or take a
+ * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
+ * other, so this is a suggested directive.
+ * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
+ * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
+ * @extends EventDispatcher
+ */
+function AbstractLoader(loadItem, preferXHR, type) {
+ this.EventDispatcher_constructor();
+ // public properties
/**
- * Defines a GET request, use for a method value when loading data.
- * @property GET
- * @type {string}
- * @default get
- * @static
+ * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
+ * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
+ * @property loaded
+ * @type {Boolean}
+ * @default false
*/
- s.GET = "GET";
+ this.loaded = false;
/**
- * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
- * @property BINARY
- * @type {String}
- * @default binary
- * @static
- * @since 0.6.0
+ * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
+ * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
+ * instead.
+ * @property canceled
+ * @type {Boolean}
+ * @default false
+ * @readonly
*/
- s.BINARY = "binary";
+ this.canceled = false;
/**
- * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a
- * <style> tag when loaded with tags.
- * @property CSS
- * @type {String}
- * @default css
- * @static
- * @since 0.6.0
+ * The current load progress (percentage) for this item. This will be a number between 0 and 1.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.loadFile("largeImage.png");
+ * queue.on("progress", function() {
+ * console.log("Progress:", queue.progress, event.progress);
+ * });
+ *
+ * @property progress
+ * @type {Number}
+ * @default 0
*/
- s.CSS = "css";
+ this.progress = 0;
/**
- * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag.
- * @property IMAGE
+ * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
+ * supported types.
+ * @property type
* @type {String}
- * @default image
- * @static
- * @since 0.6.0
*/
- s.IMAGE = "image";
+ this.type = type;
/**
- * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
- * <script> tag.
+ * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
+ * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
+ * can be overridden to provide custom formatting.
*
- * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
- * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
- * only tag-loaded scripts are injected.
- * @property JAVASCRIPT
- * @type {String}
- * @default javascript
- * @static
- * @since 0.6.0
+ * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
+ * asynchronous, such as creating a new image. The callback function is passed 2 parameters, which are callbacks
+ * to handle success and error conditions in the resultFormatter. Note that the resultFormatter method is
+ * called in the current scope, as well as the success and error callbacks.
+ *
+ * Example asynchronous resultFormatter
+ *
+ * function _formatResult(loader) {
+ * return function(success, error) {
+ * if (errorCondition) { error(errorDetailEvent); }
+ * success(result);
+ * }
+ * }
+ * @property resultFormatter
+ * @type {Function}
+ * @default null
*/
- s.JAVASCRIPT = "javascript";
+ this.resultFormatter = null;
+ // protected properties
/**
- * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
- * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
- * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
- * must contain a matching wrapper function.
- * @property JSON
- * @type {String}
- * @default json
- * @static
- * @since 0.6.0
+ * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
+ * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
+ * @property _item
+ * @type {LoadItem|Object}
+ * @private
*/
- s.JSON = "json";
+ if (loadItem) {
+ this._item = LoadItem.create(loadItem);
+ } else {
+ this._item = null;
+ }
/**
- * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
- * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
- * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
- * property is set to.
- * @property JSONP
- * @type {String}
- * @default jsonp
- * @static
- * @since 0.6.0
+ * Whether the loader will try and load content using XHR (true) or HTML tags (false).
+ * @property _preferXHR
+ * @type {Boolean}
+ * @private
*/
- s.JSONP = "jsonp";
+ this._preferXHR = preferXHR;
/**
- * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
- * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
- * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
- * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
- * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
- * @property MANIFEST
- * @type {String}
- * @default manifest
- * @static
- * @since 0.6.0
+ * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
+ * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
+ * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
+ * @property _result
+ * @type {Object|String}
+ * @private
*/
- s.MANIFEST = "manifest";
+ this._result = null;
/**
- * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
- * <audio> tag.
- * @property SOUND
- * @type {String}
- * @default sound
- * @static
- * @since 0.6.0
+ * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
+ * method, and passing `true`.
+ * @property _rawResult
+ * @type {Object|String}
+ * @private
*/
- s.SOUND = "sound";
+ this._rawResult = null;
/**
- * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
- * <video> tag.
- * @property VIDEO
- * @type {String}
- * @default video
- * @static
- * @since 0.6.0
+ * A list of items that loaders load behind the scenes. This does not include the main item the loader is
+ * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
+ * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
+ * @property _loadItems
+ * @type {null}
+ * @protected
*/
- s.VIDEO = "video";
+ this._loadedItems = null;
/**
- * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
- * @property SPRITESHEET
- * @type {String}
- * @default spritesheet
- * @static
- * @since 0.6.0
+ * The attribute the items loaded using tags use for the source.
+ * @type {string}
+ * @default null
+ * @private
*/
- s.SPRITESHEET = "spritesheet";
+ this._tagSrcAttribute = null;
/**
- * The preload type for SVG files.
- * @property SVG
- * @type {String}
- * @default svg
- * @static
- * @since 0.6.0
+ * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
+ * @property _tag
+ * @type {Object}
+ * @private
*/
- s.SVG = "svg";
+ this._tag = null;
+};
- /**
- * The preload type for text files, which is also the default file type if the type can not be determined. Text is
- * loaded as raw text.
- * @property TEXT
- * @type {String}
- * @default text
- * @static
- * @since 0.6.0
- */
- s.TEXT = "text";
+var p = extend(AbstractLoader, EventDispatcher);
+var s = AbstractLoader;
- /**
- * The preload type for xml files. XML is loaded into an XML document.
- * @property XML
- * @type {String}
- * @default xml
- * @static
- * @since 0.6.0
- */
- s.XML = "xml";
+// TODO: deprecated
+// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
-// Events
- /**
- * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
- * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
- * @event progress
- * @since 0.3.0
- */
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
- * @event loadstart
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type.
- * @since 0.3.1
- */
+/**
+ * Defines a POST request, use for a method value when loading data.
+ * @property POST
+ * @type {string}
+ * @default post
+ * @static
+ */
+s.POST = "POST";
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
- * @event complete
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type.
- * @since 0.3.0
- */
+/**
+ * Defines a GET request, use for a method value when loading data.
+ * @property GET
+ * @type {string}
+ * @default get
+ * @static
+ */
+s.GET = "GET";
- /**
- * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
- * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
- * just a regular {{#crossLink "Event"}}{{/crossLink}}.
- * @event error
- * @since 0.3.0
- */
+/**
+ * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
+ * @property BINARY
+ * @type {String}
+ * @default binary
+ * @static
+ * @since 0.6.0
+ */
+s.BINARY = "binary";
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
- * This enables loaders to maintain internal queues, and surface file load errors.
- * @event fileerror
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The even type ("fileerror")
- * @param {LoadItem|object} The item that encountered the error
- * @since 0.6.0
- */
+/**
+ * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a
+ * <style> tag when loaded with tags.
+ * @property CSS
+ * @type {String}
+ * @default css
+ * @static
+ * @since 0.6.0
+ */
+s.CSS = "css";
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
- * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
- * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
- * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
- * @event fileload
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type ("fileload")
- * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
- * object will contain that value as a `src` property.
- * @param {Object} result The HTML tag or parsed result of the loaded item.
- * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
- * to a usable object.
- * @since 0.6.0
- */
+/**
+ * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag.
+ * @property IMAGE
+ * @type {String}
+ * @default image
+ * @static
+ * @since 0.6.0
+ */
+s.IMAGE = "image";
- /**
- * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
- * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
- * @event initialize
- * @param {Object} target The object that dispatched the event.
- * @param {String} type The event type ("initialize")
- * @param {AbstractLoader} loader The loader that has been initialized.
- */
+/**
+ * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
+ * <script> tag.
+ *
+ * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
+ * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
+ * only tag-loaded scripts are injected.
+ * @property JAVASCRIPT
+ * @type {String}
+ * @default javascript
+ * @static
+ * @since 0.6.0
+ */
+s.JAVASCRIPT = "javascript";
+/**
+ * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
+ * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
+ * must contain a matching wrapper function.
+ * @property JSON
+ * @type {String}
+ * @default json
+ * @static
+ * @since 0.6.0
+ */
+s.JSON = "json";
- /**
- * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
- * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
- * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
- * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
- * @method getItem
- * @return {Object} The manifest item that this loader is responsible for loading.
- * @since 0.6.0
- */
- p.getItem = function () {
- return this._item;
- };
+/**
+ * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
+ * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
+ * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
+ * property is set to.
+ * @property JSONP
+ * @type {String}
+ * @default jsonp
+ * @static
+ * @since 0.6.0
+ */
+s.JSONP = "jsonp";
- /**
- * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
- * event is dispatched.
- * @method getResult
- * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
- * data (if it exists).
- * @return {Object}
- * @since 0.6.0
- */
- p.getResult = function (raw) {
- return raw ? this._rawResult : this._result;
- };
+/**
+ * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
+ * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
+ * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
+ * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
+ * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
+ * @property MANIFEST
+ * @type {String}
+ * @default manifest
+ * @static
+ * @since 0.6.0
+ */
+s.MANIFEST = "manifest";
- /**
- * Return the `tag` this object creates or uses for loading.
- * @method getTag
- * @return {Object} The tag instance
- * @since 0.6.0
- */
- p.getTag = function () {
- return this._tag;
- };
+/**
+ * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
+ * <audio> tag.
+ * @property SOUND
+ * @type {String}
+ * @default sound
+ * @static
+ * @since 0.6.0
+ */
+s.SOUND = "sound";
- /**
- * Set the `tag` this item uses for loading.
- * @method setTag
- * @param {Object} tag The tag instance
- * @since 0.6.0
- */
- p.setTag = function(tag) {
- this._tag = tag;
- };
+/**
+ * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
+ * <video> tag.
+ * @property VIDEO
+ * @type {String}
+ * @default video
+ * @static
+ * @since 0.6.0
+ */
+s.VIDEO = "video";
- /**
- * Begin loading the item. This method is required when using a loader by itself.
- *
- * Example
- *
- * var queue = new createjs.LoadQueue();
- * queue.on("complete", handleComplete);
- * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
- * queue.load();
- *
- * @method load
- */
- p.load = function () {
- this._createRequest();
+/**
+ * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
+ * @property SPRITESHEET
+ * @type {String}
+ * @default spritesheet
+ * @static
+ * @since 0.6.0
+ */
+s.SPRITESHEET = "spritesheet";
- this._request.on("complete", this, this);
- this._request.on("progress", this, this);
- this._request.on("loadStart", this, this);
- this._request.on("abort", this, this);
- this._request.on("timeout", this, this);
- this._request.on("error", this, this);
+/**
+ * The preload type for SVG files.
+ * @property SVG
+ * @type {String}
+ * @default svg
+ * @static
+ * @since 0.6.0
+ */
+s.SVG = "svg";
- var evt = new createjs.Event("initialize");
- evt.loader = this._request;
- this.dispatchEvent(evt);
+/**
+ * The preload type for text files, which is also the default file type if the type can not be determined. Text is
+ * loaded as raw text.
+ * @property TEXT
+ * @type {String}
+ * @default text
+ * @static
+ * @since 0.6.0
+ */
+s.TEXT = "text";
- this._request.load();
- };
+/**
+ * The preload type for xml files. XML is loaded into an XML document.
+ * @property XML
+ * @type {String}
+ * @default xml
+ * @static
+ * @since 0.6.0
+ */
+s.XML = "xml";
- /**
- * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
- * the background), but events will not longer be dispatched.
- * @method cancel
- */
- p.cancel = function () {
- this.canceled = true;
- this.destroy();
- };
+// Events
+/**
+ * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
+ * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event progress
+ * @since 0.3.0
+ */
- /**
- * Clean up the loader.
- * @method destroy
- */
- p.destroy = function() {
- if (this._request) {
- this._request.removeAllEventListeners();
- this._request.destroy();
- }
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
+ * @event loadstart
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.1
+ */
- this._request = null;
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
+ * @event complete
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type.
+ * @since 0.3.0
+ */
- this._item = null;
- this._rawResult = null;
- this._result = null;
+/**
+ * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
+ * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
+ * just a regular {{#crossLink "Event"}}{{/crossLink}}.
+ * @event error
+ * @since 0.3.0
+ */
- this._loadItems = null;
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
+ * This enables loaders to maintain internal queues, and surface file load errors.
+ * @event fileerror
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The even type ("fileerror")
+ * @param {LoadItem|object} The item that encountered the error
+ * @since 0.6.0
+ */
- this.removeAllEventListeners();
- };
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
+ * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
+ * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
+ * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
+ * @event fileload
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("fileload")
+ * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
+ * object will contain that value as a `src` property.
+ * @param {Object} result The HTML tag or parsed result of the loaded item.
+ * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
+ * to a usable object.
+ * @since 0.6.0
+ */
- /**
- * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
- * to expose items it loads internally.
- * @method getLoadedItems
- * @return {Array} A list of the items loaded by the loader.
- * @since 0.6.0
- */
- p.getLoadedItems = function () {
- return this._loadedItems;
- };
+/**
+ * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
+ * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
+ * @event initialize
+ * @param {Object} target The object that dispatched the event.
+ * @param {String} type The event type ("initialize")
+ * @param {AbstractLoader} loader The loader that has been initialized.
+ */
- // Private methods
- /**
- * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
- * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
- * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
- * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
- * @method _createRequest
- * @protected
- */
- p._createRequest = function() {
- if (!this._preferXHR) {
- this._request = new createjs.TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
- } else {
- this._request = new createjs.XHRRequest(this._item);
- }
- };
+/**
+ * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
+ * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
+ * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
+ * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
+ * @method getItem
+ * @return {Object} The manifest item that this loader is responsible for loading.
+ * @since 0.6.0
+ */
+p.getItem = function () {
+ return this._item;
+};
- /**
- * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
- * by loaders that require tag loading.
- * @method _createTag
- * @param {String} src The tag source
- * @return {HTMLElement} The tag that was created
- * @protected
- */
- p._createTag = function(src) { return null; };
+/**
+ * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
+ * event is dispatched.
+ * @method getResult
+ * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
+ * data (if it exists).
+ * @return {Object}
+ * @since 0.6.0
+ */
+p.getResult = function (raw) {
+ return raw ? this._rawResult : this._result;
+};
- /**
- * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
- * event for details on the event payload.
- * @method _sendLoadStart
- * @protected
- */
- p._sendLoadStart = function () {
- if (this._isCanceled()) { return; }
- this.dispatchEvent("loadstart");
- };
+/**
+ * Return the `tag` this object creates or uses for loading.
+ * @method getTag
+ * @return {Object} The tag instance
+ * @since 0.6.0
+ */
+p.getTag = function () {
+ return this._tag;
+};
- /**
- * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
- * @method _sendProgress
- * @param {Number | Object} value The progress of the loaded item, or an object containing loaded
- * and total
properties.
- * @protected
- */
- p._sendProgress = function (value) {
- if (this._isCanceled()) { return; }
- var event = null;
- if (typeof(value) == "number") {
- this.progress = value;
- event = new createjs.ProgressEvent(this.progress);
- } else {
- event = value;
- this.progress = value.loaded / value.total;
- event.progress = this.progress;
- if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
- }
- this.hasEventListener("progress") && this.dispatchEvent(event);
- };
+/**
+ * Set the `tag` this item uses for loading.
+ * @method setTag
+ * @param {Object} tag The tag instance
+ * @since 0.6.0
+ */
+p.setTag = function (tag) {
+ this._tag = tag;
+};
- /**
- * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
- * @method _sendComplete
- * @protected
- */
- p._sendComplete = function () {
- if (this._isCanceled()) { return; }
+/**
+ * Begin loading the item. This method is required when using a loader by itself.
+ *
+ * Example
+ *
+ * var queue = new createjs.LoadQueue();
+ * queue.on("complete", handleComplete);
+ * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
+ * queue.load();
+ *
+ * @method load
+ */
+p.load = function () {
+ this._createRequest();
- this.loaded = true;
+ this._request.on("complete", this, this);
+ this._request.on("progress", this, this);
+ this._request.on("loadStart", this, this);
+ this._request.on("abort", this, this);
+ this._request.on("timeout", this, this);
+ this._request.on("error", this, this);
- var event = new createjs.Event("complete");
- event.rawResult = this._rawResult;
+ var evt = new Event("initialize");
+ evt.loader = this._request;
+ this.dispatchEvent(evt);
- if (this._result != null) {
- event.result = this._result;
- }
+ this._request.load();
+};
- this.dispatchEvent(event);
- };
+/**
+ * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
+ * the background), but events will not longer be dispatched.
+ * @method cancel
+ */
+p.cancel = function () {
+ this.canceled = true;
+ this.destroy();
+};
- /**
- * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
- * event for details on the event payload.
- * @method _sendError
- * @param {ErrorEvent} event The event object containing specific error properties.
- * @protected
- */
- p._sendError = function (event) {
- if (this._isCanceled() || !this.hasEventListener("error")) { return; }
- if (event == null) {
- event = new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
- }
- this.dispatchEvent(event);
- };
+/**
+ * Clean up the loader.
+ * @method destroy
+ */
+p.destroy = function () {
+ if (this._request) {
+ this._request.removeAllEventListeners();
+ this._request.destroy();
+ }
- /**
- * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
- * do not cause issues after the queue has been cleaned up.
- * @method _isCanceled
- * @return {Boolean} If the loader has been canceled.
- * @protected
- */
- p._isCanceled = function () {
- if (window.createjs == null || this.canceled) {
- return true;
- }
- return false;
- };
+ this._request = null;
- /**
- * A custom result formatter function, which is called just before a request dispatches its complete event. Most
- * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
- * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
- * @property resultFormatter
- * @type Function
- * @return {Object} The formatted result
- * @since 0.6.0
- */
- p.resultFormatter = null;
+ this._item = null;
+ this._rawResult = null;
+ this._result = null;
- /**
- * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
- * this method can be overridden for custom behaviours.
- * @method handleEvent
- * @param {Event} event The event that the internal request dispatches.
- * @protected
- * @since 0.6.0
- */
- p.handleEvent = function (event) {
- switch (event.type) {
- case "complete":
- this._rawResult = event.target._response;
- var result = this.resultFormatter && this.resultFormatter(this);
- if (result instanceof Function) {
- result.call(this,
- createjs.proxy(this._resultFormatSuccess, this),
- createjs.proxy(this._resultFormatFailed, this)
- );
- } else {
- this._result = result || this._rawResult;
- this._sendComplete();
- }
- break;
- case "progress":
- this._sendProgress(event);
- break;
- case "error":
- this._sendError(event);
- break;
- case "loadstart":
- this._sendLoadStart();
- break;
- case "abort":
- case "timeout":
- if (!this._isCanceled()) {
- this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR"));
- }
- break;
+ this._loadItems = null;
+
+ this.removeAllEventListeners();
+};
+
+/**
+ * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
+ * to expose items it loads internally.
+ * @method getLoadedItems
+ * @return {Array} A list of the items loaded by the loader.
+ * @since 0.6.0
+ */
+p.getLoadedItems = function () {
+ return this._loadedItems;
+};
+
+
+// Private methods
+/**
+ * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
+ * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
+ * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
+ * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
+ * @method _createRequest
+ * @protected
+ */
+p._createRequest = function () {
+ if (!this._preferXHR) {
+ this._request = new TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
+ } else {
+ this._request = new XHRRequest(this._item);
+ }
+};
+
+/**
+ * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
+ * by loaders that require tag loading.
+ * @method _createTag
+ * @param {String} src The tag source
+ * @return {HTMLElement} The tag that was created
+ * @protected
+ */
+p._createTag = function (src) {
+ return null;
+};
+
+/**
+ * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendLoadStart
+ * @protected
+ */
+p._sendLoadStart = function () {
+ if (this._isCanceled()) {
+ return;
+ }
+ this.dispatchEvent("loadstart");
+};
+
+/**
+ * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
+ * @method _sendProgress
+ * @param {Number | Object} value The progress of the loaded item, or an object containing loaded
+ * and total
properties.
+ * @protected
+ */
+p._sendProgress = function (value) {
+ if (this._isCanceled()) {
+ return;
+ }
+ var event = null;
+ if (typeof(value) == "number") {
+ this.progress = value;
+ event = new ProgressEvent(this.progress);
+ } else {
+ event = value;
+ this.progress = value.loaded / value.total;
+ event.progress = this.progress;
+ if (isNaN(this.progress) || this.progress == Infinity) {
+ this.progress = 0;
}
- };
+ }
+ this.hasEventListener("progress") && this.dispatchEvent(event);
+};
- /**
- * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
- * functions.
- * @method _resultFormatSuccess
- * @param {Object} result The formatted result
- * @private
- */
- p._resultFormatSuccess = function (result) {
- this._result = result;
- this._sendComplete();
- };
+/**
+ * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
+ * @method _sendComplete
+ * @protected
+ */
+p._sendComplete = function () {
+ if (this._isCanceled()) {
+ return;
+ }
- /**
- * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
- * functions.
- * @method _resultFormatSuccess
- * @param {Object} error The error event
- * @private
- */
- p._resultFormatFailed = function (event) {
- this._sendError(event);
- };
+ this.loaded = true;
- /**
- * @method buildPath
- * @protected
- * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
- * instead.
- */
- p.buildPath = function (src, data) {
- return createjs.RequestUtils.buildPath(src, data);
- };
+ var event = new Event("complete");
+ event.rawResult = this._rawResult;
- /**
- * @method toString
- * @return {String} a string representation of the instance.
- */
- p.toString = function () {
- return "[PreloadJS AbstractLoader]";
- };
+ if (this._result != null) {
+ event.result = this._result;
+ }
+
+ this.dispatchEvent(event);
+};
- createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher");
+/**
+ * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
+ * event for details on the event payload.
+ * @method _sendError
+ * @param {ErrorEvent} event The event object containing specific error properties.
+ * @protected
+ */
+p._sendError = function (event) {
+ if (this._isCanceled() || !this.hasEventListener("error")) {
+ return;
+ }
+ if (event == null) {
+ event = new ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
+ }
+ this.dispatchEvent(event);
+};
+
+/**
+ * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
+ * do not cause issues after the queue has been cleaned up.
+ * @method _isCanceled
+ * @return {Boolean} If the loader has been canceled.
+ * @protected
+ */
+p._isCanceled = function () {
+ if (window.createjs == null || this.canceled) {
+ return true;
+ }
+ return false;
+};
+
+/**
+ * A custom result formatter function, which is called just before a request dispatches its complete event. Most
+ * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
+ * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
+ * @property resultFormatter
+ * @type Function
+ * @return {Object} The formatted result
+ * @since 0.6.0
+ */
+p.resultFormatter = null;
+
+/**
+ * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
+ * this method can be overridden for custom behaviours.
+ * @method handleEvent
+ * @param {Event} event The event that the internal request dispatches.
+ * @protected
+ * @since 0.6.0
+ */
+p.handleEvent = function (event) {
+ switch (event.type) {
+ case "complete":
+ this._rawResult = event.target._response;
+ var result = this.resultFormatter && this.resultFormatter(this);
+ if (result instanceof Function) {
+ result.call(this,
+ proxy(this._resultFormatSuccess, this),
+ proxy(this._resultFormatFailed, this)
+ );
+ } else {
+ this._result = result || this._rawResult;
+ this._sendComplete();
+ }
+ break;
+ case "progress":
+ this._sendProgress(event);
+ break;
+ case "error":
+ this._sendError(event);
+ break;
+ case "loadstart":
+ this._sendLoadStart();
+ break;
+ case "abort":
+ case "timeout":
+ if (!this._isCanceled()) {
+ this.dispatchEvent(new ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR"));
+ }
+ break;
+ }
+};
+
+/**
+ * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} result The formatted result
+ * @private
+ */
+p._resultFormatSuccess = function (result) {
+ this._result = result;
+ this._sendComplete();
+};
+
+/**
+ * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous
+ * functions.
+ * @method _resultFormatSuccess
+ * @param {Object} error The error event
+ * @private
+ */
+p._resultFormatFailed = function (event) {
+ this._sendError(event);
+};
+
+/**
+ * @method buildPath
+ * @protected
+ * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
+ * instead.
+ */
+p.buildPath = function (src, data) {
+ return RequestUtils.buildPath(src, data);
+};
+
+/**
+ * @method toString
+ * @return {String} a string representation of the instance.
+ */
+p.toString = function () {
+ return "[PreloadJS AbstractLoader]";
+};
-}());
+module.exports = AbstractLoader = promote(AbstractLoader, "EventDispatcher");
diff --git a/src/preloadjs/loaders/AbstractMediaLoader.js b/src/preloadjs/loaders/AbstractMediaLoader.js
index a3a0298..b089814 100644
--- a/src/preloadjs/loaders/AbstractMediaLoader.js
+++ b/src/preloadjs/loaders/AbstractMediaLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -128,4 +129,4 @@ this.createjs = this.createjs || {};
createjs.AbstractMediaLoader = createjs.promote(AbstractMediaLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/BinaryLoader.js b/src/preloadjs/loaders/BinaryLoader.js
index 8195a66..3a07b8b 100644
--- a/src/preloadjs/loaders/BinaryLoader.js
+++ b/src/preloadjs/loaders/BinaryLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -79,4 +80,4 @@ this.createjs = this.createjs || {};
createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/CSSLoader.js b/src/preloadjs/loaders/CSSLoader.js
index 2eb7160..a9ba1cb 100644
--- a/src/preloadjs/loaders/CSSLoader.js
+++ b/src/preloadjs/loaders/CSSLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -110,4 +111,4 @@ this.createjs = this.createjs || {};
createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/ImageLoader.js b/src/preloadjs/loaders/ImageLoader.js
index 4768588..a494462 100644
--- a/src/preloadjs/loaders/ImageLoader.js
+++ b/src/preloadjs/loaders/ImageLoader.js
@@ -27,157 +27,159 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-// namespace:
-this.createjs = this.createjs || {};
-
-(function () {
- "use strict";
-
- // constructor
- /**
- * A loader for image files.
- * @class ImageLoader
- * @param {LoadItem|Object} loadItem
- * @param {Boolean} preferXHR
- * @extends AbstractLoader
- * @constructor
- */
- function ImageLoader (loadItem, preferXHR) {
- this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE);
-
- // public properties
- this.resultFormatter = this._formatResult;
-
- // protected properties
- this._tagSrcAttribute = "src";
-
- // Check if the preload item is already a tag.
- if (createjs.RequestUtils.isImageTag(loadItem)) {
- this._tag = loadItem;
- } else if (createjs.RequestUtils.isImageTag(loadItem.src)) {
- this._tag = loadItem.src;
- } else if (createjs.RequestUtils.isImageTag(loadItem.tag)) {
- this._tag = loadItem.tag;
- }
-
- if (this._tag != null) {
- this._preferXHR = false;
- } else {
- this._tag = document.createElement("img");
- }
-
- this.on("initialize", this._updateXHR, this);
- };
-
- var p = createjs.extend(ImageLoader, createjs.AbstractLoader);
- var s = ImageLoader;
-
- // static methods
- /**
- * Determines if the loader can load a specific item. This loader can only load items that are of type
- * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
- * @method canLoadItem
- * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
- * @returns {Boolean} Whether the loader can load the item.
- * @static
- */
- s.canLoadItem = function (item) {
- return item.type == createjs.AbstractLoader.IMAGE;
- };
-
- // public methods
- p.load = function () {
- if (this._tag.src != "" && this._tag.complete) {
- this._sendComplete();
- return;
- }
-
- var crossOrigin = this._item.crossOrigin;
- if (crossOrigin == true) { crossOrigin = "Anonymous"; }
- if (crossOrigin != null && !createjs.RequestUtils.isLocal(this._item.src)) {
- this._tag.crossOrigin = crossOrigin;
- }
-
- this.AbstractLoader_load();
- };
-
- // protected methods
- /**
- * Before the item loads, set its mimeType and responseType.
- * @property _updateXHR
- * @param {Event} event
- * @private
- */
- p._updateXHR = function (event) {
- event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';
-
- // Only exists for XHR
- if (event.loader.setResponseType) {
- event.loader.setResponseType("blob");
- }
- };
-
- /**
- * The result formatter for Image files.
- * @method _formatResult
- * @param {AbstractLoader} loader
- * @returns {HTMLImageElement}
- * @private
- */
- p._formatResult = function (loader) {
- return this._formatImage;
- };
-
- /**
- * The asynchronous image formatter function. This is required because images have
- * a short delay before they are ready.
- * @method _formatImage
- * @param {Function} successCallback The method to call when the result has finished formatting
- * @param {Function} errorCallback The method to call if an error occurs during formatting
- * @private
- */
- p._formatImage = function (successCallback, errorCallback) {
- var tag = this._tag;
- var URL = window.URL || window.webkitURL;
-
- if (!this._preferXHR) {
- //document.body.removeChild(tag);
- } else if (URL) {
- var objURL = URL.createObjectURL(this.getResult(true));
- tag.src = objURL;
-
- tag.addEventListener("load", this._cleanUpURL, false);
- tag.addEventListener("error", this._cleanUpURL, false);
- } else {
- tag.src = this._item.src;
- }
-
- if (tag.complete) {
- successCallback(tag);
- } else {
- tag.onload = createjs.proxy(function() {
- successCallback(this._tag);
- }, this);
-
- tag.onerror = createjs.proxy(function() {
- errorCallback(_this._tag);
- }, this);
- }
- };
-
- /**
- * Clean up the ObjectURL, the tag is done with it. Note that this function is run
- * as an event listener without a proxy/closure, as it doesn't require it - so do not
- * include any functionality that requires scope without changing it.
- * @method _cleanUpURL
- * @param event
- * @private
- */
- p._cleanUpURL = function (event) {
- var URL = window.URL || window.webkitURL;
- URL.revokeObjectURL(event.target.src);
- };
-
- createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader");
-
-}());
+// constructor
+/**
+ * A loader for image files.
+ * @class ImageLoader
+ * @param {LoadItem|Object} loadItem
+ * @param {Boolean} preferXHR
+ * @extends AbstractLoader
+ * @constructor
+ */
+
+var AbstractLoader = require('./AbstractLoader');
+var RequestUtils = require('../utils/RequestUtils');
+var extend = require('../../createjs/utils/extend');
+var promote = require('../../createjs/utils/promote');
+var proxy = require('../../createjs/utils/proxy');
+
+function ImageLoader(loadItem, preferXHR) {
+ this.AbstractLoader_constructor(loadItem, preferXHR, AbstractLoader.IMAGE);
+
+ // public properties
+ this.resultFormatter = this._formatResult;
+
+ // protected properties
+ this._tagSrcAttribute = "src";
+
+ // Check if the preload item is already a tag.
+ if (RequestUtils.isImageTag(loadItem)) {
+ this._tag = loadItem;
+ } else if (RequestUtils.isImageTag(loadItem.src)) {
+ this._tag = loadItem.src;
+ } else if (RequestUtils.isImageTag(loadItem.tag)) {
+ this._tag = loadItem.tag;
+ }
+
+ if (this._tag != null) {
+ this._preferXHR = false;
+ } else {
+ this._tag = document.createElement("img");
+ }
+
+ this.on("initialize", this._updateXHR, this);
+};
+
+var p = extend(ImageLoader, AbstractLoader);
+var s = ImageLoader;
+
+// static methods
+/**
+ * Determines if the loader can load a specific item. This loader can only load items that are of type
+ * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
+ * @method canLoadItem
+ * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
+ * @returns {Boolean} Whether the loader can load the item.
+ * @static
+ */
+s.canLoadItem = function (item) {
+ return item.type == AbstractLoader.IMAGE;
+};
+
+// public methods
+p.load = function () {
+ if (this._tag.src != "" && this._tag.complete) {
+ this._sendComplete();
+ return;
+ }
+
+ var crossOrigin = this._item.crossOrigin;
+ if (crossOrigin == true) {
+ crossOrigin = "Anonymous";
+ }
+ if (crossOrigin != null && !RequestUtils.isLocal(this._item.src)) {
+ this._tag.crossOrigin = crossOrigin;
+ }
+
+ this.AbstractLoader_load();
+};
+
+// protected methods
+/**
+ * Before the item loads, set its mimeType and responseType.
+ * @property _updateXHR
+ * @param {Event} event
+ * @private
+ */
+p._updateXHR = function (event) {
+ event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';
+
+ // Only exists for XHR
+ if (event.loader.setResponseType) {
+ event.loader.setResponseType("blob");
+ }
+};
+
+/**
+ * The result formatter for Image files.
+ * @method _formatResult
+ * @param {AbstractLoader} loader
+ * @returns {HTMLImageElement}
+ * @private
+ */
+p._formatResult = function (loader) {
+ return this._formatImage;
+};
+
+/**
+ * The asynchronous image formatter function. This is required because images have
+ * a short delay before they are ready.
+ * @method _formatImage
+ * @param {Function} successCallback The method to call when the result has finished formatting
+ * @param {Function} errorCallback The method to call if an error occurs during formatting
+ * @private
+ */
+p._formatImage = function (successCallback, errorCallback) {
+ var tag = this._tag;
+ var URL = window.URL || window.webkitURL;
+
+ if (!this._preferXHR) {
+ //document.body.removeChild(tag);
+ } else if (URL) {
+ var objURL = URL.createObjectURL(this.getResult(true));
+ tag.src = objURL;
+
+ tag.addEventListener("load", this._cleanUpURL, false);
+ tag.addEventListener("error", this._cleanUpURL, false);
+ } else {
+ tag.src = this._item.src;
+ }
+
+ if (tag.complete) {
+ successCallback(tag);
+ } else {
+ tag.onload = proxy(function () {
+ successCallback(this._tag);
+ }, this);
+
+ tag.onerror = proxy(function () {
+ errorCallback(_this._tag);
+ }, this);
+ }
+};
+
+/**
+ * Clean up the ObjectURL, the tag is done with it. Note that this function is run
+ * as an event listener without a proxy/closure, as it doesn't require it - so do not
+ * include any functionality that requires scope without changing it.
+ * @method _cleanUpURL
+ * @param event
+ * @private
+ */
+p._cleanUpURL = function (event) {
+ var URL = window.URL || window.webkitURL;
+ URL.revokeObjectURL(event.target.src);
+};
+
+var ImageLoader = promote(ImageLoader, "AbstractLoader");
+module.exports = ImageLoader;
diff --git a/src/preloadjs/loaders/JSONLoader.js b/src/preloadjs/loaders/JSONLoader.js
index e088ae9..7628818 100644
--- a/src/preloadjs/loaders/JSONLoader.js
+++ b/src/preloadjs/loaders/JSONLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -93,4 +94,4 @@ this.createjs = this.createjs || {};
createjs.JSONLoader = createjs.promote(JSONLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/JSONPLoader.js b/src/preloadjs/loaders/JSONPLoader.js
index bbb21e6..2ef8889 100644
--- a/src/preloadjs/loaders/JSONPLoader.js
+++ b/src/preloadjs/loaders/JSONPLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -177,4 +178,4 @@ this.createjs = this.createjs || {};
createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/JavaScriptLoader.js b/src/preloadjs/loaders/JavaScriptLoader.js
index 576c989..025e466 100644
--- a/src/preloadjs/loaders/JavaScriptLoader.js
+++ b/src/preloadjs/loaders/JavaScriptLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -91,4 +92,4 @@ this.createjs = this.createjs || {};
createjs.JavaScriptLoader = createjs.promote(JavaScriptLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/ManifestLoader.js b/src/preloadjs/loaders/ManifestLoader.js
index 53d59e2..2bd79c9 100644
--- a/src/preloadjs/loaders/ManifestLoader.js
+++ b/src/preloadjs/loaders/ManifestLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -226,4 +227,4 @@ this.createjs = this.createjs || {};
createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/SVGLoader.js b/src/preloadjs/loaders/SVGLoader.js
index 2f12dff..4177b7b 100644
--- a/src/preloadjs/loaders/SVGLoader.js
+++ b/src/preloadjs/loaders/SVGLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -107,4 +108,4 @@ this.createjs = this.createjs || {};
createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/SoundLoader.js b/src/preloadjs/loaders/SoundLoader.js
index a3be741..6d80165 100644
--- a/src/preloadjs/loaders/SoundLoader.js
+++ b/src/preloadjs/loaders/SoundLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -95,4 +96,4 @@ this.createjs = this.createjs || {};
createjs.SoundLoader = createjs.promote(SoundLoader, "AbstractMediaLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/SpriteSheetLoader.js b/src/preloadjs/loaders/SpriteSheetLoader.js
index af8ee32..e6c3bd6 100644
--- a/src/preloadjs/loaders/SpriteSheetLoader.js
+++ b/src/preloadjs/loaders/SpriteSheetLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -204,4 +205,4 @@ this.createjs = this.createjs || {};
createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/TextLoader.js b/src/preloadjs/loaders/TextLoader.js
index 58f7d11..5e4be86 100644
--- a/src/preloadjs/loaders/TextLoader.js
+++ b/src/preloadjs/loaders/TextLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -67,4 +68,4 @@ this.createjs = this.createjs || {};
createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/VideoLoader.js b/src/preloadjs/loaders/VideoLoader.js
index da2f2b3..ccaa242 100644
--- a/src/preloadjs/loaders/VideoLoader.js
+++ b/src/preloadjs/loaders/VideoLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -87,4 +88,4 @@ this.createjs = this.createjs || {};
createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/loaders/XMLLoader.js b/src/preloadjs/loaders/XMLLoader.js
index a2cb16a..1255ac9 100644
--- a/src/preloadjs/loaders/XMLLoader.js
+++ b/src/preloadjs/loaders/XMLLoader.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -82,4 +83,4 @@ this.createjs = this.createjs || {};
createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/net/AbstractRequest.js b/src/preloadjs/net/AbstractRequest.js
index ccb10ae..0a0710e 100644
--- a/src/preloadjs/net/AbstractRequest.js
+++ b/src/preloadjs/net/AbstractRequest.js
@@ -31,45 +31,44 @@
* @module PreloadJS
*/
-// namespace:
-this.createjs = this.createjs || {};
+var promote = require('../../createjs/utils/promote');
+var extend = require('../../createjs/utils/extend');
+var EventDispatcher = require('../../createjs/events/EventDispatcher');
-(function () {
- "use strict";
-
- /**
- * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
- * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
- * hood to get data.
- * @class AbstractRequest
- * @param {LoadItem} item
- * @constructor
- */
- var AbstractRequest = function (item) {
- this._item = item;
- };
-
- var p = createjs.extend(AbstractRequest, createjs.EventDispatcher);
+/**
+ * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
+ * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
+ * hood to get data.
+ * @class AbstractRequest
+ * @param {LoadItem} item
+ * @constructor
+ */
+var AbstractRequest = function (item) {
+ this._item = item;
+};
- // public methods
- /**
- * Begin a load.
- * @method load
- */
- p.load = function() {};
+var p = extend(AbstractRequest, EventDispatcher);
- /**
- * Clean up a request.
- * @method destroy
- */
- p.destroy = function() {};
+// public methods
+/**
+ * Begin a load.
+ * @method load
+ */
+p.load = function () {
+};
- /**
- * Cancel an in-progress request.
- * @method cancel
- */
- p.cancel = function() {};
+/**
+ * Clean up a request.
+ * @method destroy
+ */
+p.destroy = function () {
+};
- createjs.AbstractRequest = createjs.promote(AbstractRequest, "EventDispatcher");
+/**
+ * Cancel an in-progress request.
+ * @method cancel
+ */
+p.cancel = function () {
+};
-}());
\ No newline at end of file
+module.exports = AbstractRequest = promote(AbstractRequest, "EventDispatcher");
diff --git a/src/preloadjs/net/MediaTagRequest.js b/src/preloadjs/net/MediaTagRequest.js
index 39c0fe0..88a21ff 100644
--- a/src/preloadjs/net/MediaTagRequest.js
+++ b/src/preloadjs/net/MediaTagRequest.js
@@ -32,9 +32,10 @@
*/
// namespace:
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
// constructor
@@ -118,4 +119,4 @@ this.createjs = this.createjs || {};
createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest");
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/net/TagRequest.js b/src/preloadjs/net/TagRequest.js
index 921c35c..ead17be 100644
--- a/src/preloadjs/net/TagRequest.js
+++ b/src/preloadjs/net/TagRequest.js
@@ -31,186 +31,184 @@
* @module PreloadJS
*/
-// namespace:
-this.createjs = this.createjs || {};
+var proxy = require('../../createjs/utils/proxy');
+var extend = require('../../createjs/utils/extend');
+var AbstractRequest = require('./AbstractRequest');
+var Event = require('../../createjs/events/Event');
+var promote = require('../../createjs/utils/promote');
-(function () {
- "use strict";
+// constructor
+/**
+ * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
+ * @class TagRequest
+ * @param {LoadItem} loadItem
+ * @param {HTMLElement} tag
+ * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
+ */
+function TagRequest(loadItem, tag, srcAttribute) {
+ this.AbstractRequest_constructor(loadItem);
- // constructor
- /**
- * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
- * @class TagRequest
- * @param {LoadItem} loadItem
- * @param {HTMLElement} tag
- * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
- */
- function TagRequest(loadItem, tag, srcAttribute) {
- this.AbstractRequest_constructor(loadItem);
-
- // protected properties
- /**
- * The HTML tag instance that is used to load.
- * @property _tag
- * @type {HTMLElement}
- * @protected
- */
- this._tag = tag;
-
- /**
- * The tag attribute that specifies the source, such as "src", "href", etc.
- * @property _tagSrcAttribute
- * @type {String}
- * @protected
- */
- this._tagSrcAttribute = srcAttribute;
-
- /**
- * A method closure used for handling the tag load event.
- * @property _loadedHandler
- * @type {Function}
- * @private
- */
- this._loadedHandler = createjs.proxy(this._handleTagComplete, this);
-
- /**
- * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
- * @property _addedToDOM
- * @type {Boolean}
- * @private
- */
- this._addedToDOM = false;
-
- /**
- * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
- *
- * @type {null}
- * @private
- */
- this._startTagVisibility = null;
- };
-
- var p = createjs.extend(TagRequest, createjs.AbstractRequest);
-
- // public methods
- p.load = function () {
- this._tag.onload = createjs.proxy(this._handleTagComplete, this);
- this._tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this);
- this._tag.onerror = createjs.proxy(this._handleError, this);
-
- var evt = new createjs.Event("initialize");
- evt.loader = this._tag;
-
- this.dispatchEvent(evt);
-
- this._hideTag();
-
- this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
-
- this._tag[this._tagSrcAttribute] = this._item.src;
-
- // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
- if (this._tag.parentNode == null) {
- window.document.body.appendChild(this._tag);
- this._addedToDOM = true;
- }
- };
-
- p.destroy = function() {
- this._clean();
- this._tag = null;
-
- this.AbstractRequest_destroy();
- };
-
- // private methods
+ // protected properties
/**
- * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
- * and LINK tags), but other cases may exist.
- * @method _handleReadyStateChange
- * @private
+ * The HTML tag instance that is used to load.
+ * @property _tag
+ * @type {HTMLElement}
+ * @protected
*/
- p._handleReadyStateChange = function () {
- clearTimeout(this._loadTimeout);
- // This is strictly for tags in browsers that do not support onload.
- var tag = this._tag;
-
- // Complete is for old IE support.
- if (tag.readyState == "loaded" || tag.readyState == "complete") {
- this._handleTagComplete();
- }
- };
+ this._tag = tag;
/**
- * Handle any error events from the tag.
- * @method _handleError
+ * The tag attribute that specifies the source, such as "src", "href", etc.
+ * @property _tagSrcAttribute
+ * @type {String}
* @protected
*/
- p._handleError = function() {
- this._clean();
- this.dispatchEvent("error");
- };
+ this._tagSrcAttribute = srcAttribute;
/**
- * Handle the tag's onload callback.
- * @method _handleTagComplete
+ * A method closure used for handling the tag load event.
+ * @property _loadedHandler
+ * @type {Function}
* @private
*/
- p._handleTagComplete = function () {
- this._rawResult = this._tag;
- this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;
-
- this._clean();
- this._showTag();
-
- this.dispatchEvent("complete");
- };
+ this._loadedHandler = proxy(this._handleTagComplete, this);
/**
- * The tag request has not loaded within the time specified in loadTimeout.
- * @method _handleError
- * @param {Object} event The XHR error event.
+ * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
+ * @property _addedToDOM
+ * @type {Boolean}
* @private
*/
- p._handleTimeout = function () {
- this._clean();
- this.dispatchEvent(new createjs.Event("timeout"));
- };
+ this._addedToDOM = false;
/**
- * Remove event listeners, but don't destroy the request object
- * @method _clean
+ * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
+ *
+ * @type {null}
* @private
*/
- p._clean = function() {
- this._tag.onload = null;
- this._tag.onreadystatechange = null;
- this._tag.onerror = null;
- if (this._addedToDOM && this._tag.parentNode != null) {
- this._tag.parentNode.removeChild(this._tag);
- }
- clearTimeout(this._loadTimeout);
- };
-
- p._hideTag = function() {
- this._startTagVisibility = this._tag.style.visibility;
- this._tag.style.visibility = "hidden";
- };
-
- p._showTag = function() {
- this._tag.style.visibility = this._startTagVisibility;
- };
+ this._startTagVisibility = null;
+};
- /**
- * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
- * that is already in a load, but not complete.
- * @method _handleStalled
- * @private
- */
- p._handleStalled = function () {
- //Ignore, let the timeout take care of it. Sometimes its not really stopped.
- };
+var p = extend(TagRequest, AbstractRequest);
+
+// public methods
+p.load = function () {
+ this._tag.onload = proxy(this._handleTagComplete, this);
+ this._tag.onreadystatechange = proxy(this._handleReadyStateChange, this);
+ this._tag.onerror = proxy(this._handleError, this);
+
+ var evt = new Event("initialize");
+ evt.loader = this._tag;
+
+ this.dispatchEvent(evt);
+
+ this._hideTag();
+
+ this._loadTimeout = setTimeout(proxy(this._handleTimeout, this), this._item.loadTimeout);
+
+ this._tag[this._tagSrcAttribute] = this._item.src;
+
+ // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
+ if (this._tag.parentNode == null) {
+ window.document.body.appendChild(this._tag);
+ this._addedToDOM = true;
+ }
+};
+
+p.destroy = function () {
+ this._clean();
+ this._tag = null;
+
+ this.AbstractRequest_destroy();
+};
- createjs.TagRequest = createjs.promote(TagRequest, "AbstractRequest");
+// private methods
+/**
+ * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
+ * and LINK tags), but other cases may exist.
+ * @method _handleReadyStateChange
+ * @private
+ */
+p._handleReadyStateChange = function () {
+ clearTimeout(this._loadTimeout);
+ // This is strictly for tags in browsers that do not support onload.
+ var tag = this._tag;
+
+ // Complete is for old IE support.
+ if (tag.readyState == "loaded" || tag.readyState == "complete") {
+ this._handleTagComplete();
+ }
+};
+
+/**
+ * Handle any error events from the tag.
+ * @method _handleError
+ * @protected
+ */
+p._handleError = function () {
+ this._clean();
+ this.dispatchEvent("error");
+};
+
+/**
+ * Handle the tag's onload callback.
+ * @method _handleTagComplete
+ * @private
+ */
+p._handleTagComplete = function () {
+ this._rawResult = this._tag;
+ this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;
+
+ this._clean();
+ this._showTag();
+
+ this.dispatchEvent("complete");
+};
+
+/**
+ * The tag request has not loaded within the time specified in loadTimeout.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+p._handleTimeout = function () {
+ this._clean();
+ this.dispatchEvent(new Event("timeout"));
+};
+
+/**
+ * Remove event listeners, but don't destroy the request object
+ * @method _clean
+ * @private
+ */
+p._clean = function () {
+ this._tag.onload = null;
+ this._tag.onreadystatechange = null;
+ this._tag.onerror = null;
+ if (this._addedToDOM && this._tag.parentNode != null) {
+ this._tag.parentNode.removeChild(this._tag);
+ }
+ clearTimeout(this._loadTimeout);
+};
+
+p._hideTag = function () {
+ this._startTagVisibility = this._tag.style.visibility;
+ this._tag.style.visibility = "hidden";
+};
+
+p._showTag = function () {
+ this._tag.style.visibility = this._startTagVisibility;
+};
+
+/**
+ * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
+ * that is already in a load, but not complete.
+ * @method _handleStalled
+ * @private
+ */
+p._handleStalled = function () {
+ //Ignore, let the timeout take care of it. Sometimes its not really stopped.
+};
-}());
+module.exports = promote(TagRequest, "AbstractRequest");
\ No newline at end of file
diff --git a/src/preloadjs/net/XHRRequest.js b/src/preloadjs/net/XHRRequest.js
index a5cfee6..8326dea 100644
--- a/src/preloadjs/net/XHRRequest.js
+++ b/src/preloadjs/net/XHRRequest.js
@@ -31,533 +31,533 @@
* @module PreloadJS
*/
-// namespace:
-this.createjs = this.createjs || {};
+var proxy = require('../../createjs/utils/proxy');
+var extend = require('../../createjs/utils/extend');
+var promote = require('../../createjs/utils/promote');
+var AbstractRequest = require('./AbstractRequest');
+var AbstractLoader = require('../loaders/AbstractLoader');
+var RequestUtils = require('../utils/RequestUtils');
+var ErrorEvent = require('../../createjs/events/ErrorEvent');
+var ProgressEvent = require('../events/ProgressEvent');
-(function () {
- "use strict";
+/**
+ * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
+ * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
+ * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
+ * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
+ * cross-domain loading.
+ * @class XHRRequest
+ * @constructor
+ * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
+ * for an overview of supported file properties.
+ * @extends AbstractLoader
+ */
+function XHRRequest(item) {
+ this.AbstractRequest_constructor(item);
-// constructor
+ // protected properties
/**
- * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
- * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
- * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
- * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
- * cross-domain loading.
- * @class XHRRequest
- * @constructor
- * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
- * for an overview of supported file properties.
- * @extends AbstractLoader
+ * A reference to the XHR request used to load the content.
+ * @property _request
+ * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
+ * @private
*/
- function XHRRequest (item) {
- this.AbstractRequest_constructor(item);
-
- // protected properties
- /**
- * A reference to the XHR request used to load the content.
- * @property _request
- * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
- * @private
- */
- this._request = null;
-
- /**
- * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
- * typically IE9).
- * @property _loadTimeout
- * @type {Number}
- * @private
- */
- this._loadTimeout = null;
-
- /**
- * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
- * the version, so we use capabilities to make a best guess.
- * @property _xhrLevel
- * @type {Number}
- * @default 1
- * @private
- */
- this._xhrLevel = 1;
-
- /**
- * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
- * null until the file is loaded.
- * @property _response
- * @type {mixed}
- * @private
- */
- this._response = null;
-
- /**
- * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
- * an HTML tag or a formatted object which is set to the result
property, but the developer may still
- * want to access the raw content as it was loaded.
- * @property _rawResponse
- * @type {String|Object}
- * @private
- */
- this._rawResponse = null;
-
- this._canceled = false;
-
- // Setup our event handlers now.
- this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this);
- this._handleProgressProxy = createjs.proxy(this._handleProgress, this);
- this._handleAbortProxy = createjs.proxy(this._handleAbort, this);
- this._handleErrorProxy = createjs.proxy(this._handleError, this);
- this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this);
- this._handleLoadProxy = createjs.proxy(this._handleLoad, this);
- this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this);
-
- if (!this._createXHR(item)) {
- //TODO: Throw error?
- }
- };
-
- var p = createjs.extend(XHRRequest, createjs.AbstractRequest);
+ this._request = null;
-// static properties
/**
- * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
- * @property ACTIVEX_VERSIONS
- * @type {Array}
- * @since 0.4.2
+ * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
+ * typically IE9).
+ * @property _loadTimeout
+ * @type {Number}
* @private
*/
- XHRRequest.ACTIVEX_VERSIONS = [
- "Msxml2.XMLHTTP.6.0",
- "Msxml2.XMLHTTP.5.0",
- "Msxml2.XMLHTTP.4.0",
- "MSXML2.XMLHTTP.3.0",
- "MSXML2.XMLHTTP",
- "Microsoft.XMLHTTP"
- ];
+ this._loadTimeout = null;
-// Public methods
/**
- * Look up the loaded result.
- * @method getResult
- * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
- * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
- * returned instead.
- * @return {Object} A result object containing the content that was loaded, such as:
- *
- * - An image tag (<image />) for images
- * - A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the
- * HTML head.
- * - A style tag for CSS (<style />)
- * - Raw text for TEXT
- * - A formatted JavaScript object defined by JSON
- * - An XML document
- * - An binary arraybuffer loaded by XHR
- *
- * Note that if a raw result is requested, but not found, the result will be returned instead.
- */
- p.getResult = function (raw) {
- if (raw && this._rawResponse) {
- return this._rawResponse;
- }
- return this._response;
- };
-
- // Overrides abstract method in AbstractRequest
- p.cancel = function () {
- this.canceled = true;
- this._clean();
- this._request.abort();
- };
-
- // Overrides abstract method in AbstractLoader
- p.load = function () {
- if (this._request == null) {
- this._handleError();
- return;
- }
-
- //Events
- if (this._request.addEventListener != null) {
- this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
- this._request.addEventListener("progress", this._handleProgressProxy, false);
- this._request.addEventListener("abort", this._handleAbortProxy, false);
- this._request.addEventListener("error", this._handleErrorProxy, false);
- this._request.addEventListener("timeout", this._handleTimeoutProxy, false);
-
- // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
- this._request.addEventListener("load", this._handleLoadProxy, false);
- this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
- } else {
- // IE9 support
- this._request.onloadstart = this._handleLoadStartProxy;
- this._request.onprogress = this._handleProgressProxy;
- this._request.onabort = this._handleAbortProxy;
- this._request.onerror = this._handleErrorProxy;
- this._request.ontimeout = this._handleTimeoutProxy;
-
- // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
- this._request.onload = this._handleLoadProxy;
- this._request.onreadystatechange = this._handleReadyStateChangeProxy;
- }
-
- // Set up a timeout if we don't have XHR2
- if (this._xhrLevel == 1) {
- this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
- }
-
- // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome
- try {
- if (!this._item.values || this._item.method == createjs.AbstractLoader.GET) {
- this._request.send();
- } else if (this._item.method == createjs.AbstractLoader.POST) {
- this._request.send(createjs.RequestUtils.formatQueryString(this._item.values));
- }
- } catch (error) {
- this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND", null, error));
- }
- };
-
- p.setResponseType = function (type) {
- // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
- if (type === 'blob') {
- type = window.URL ? 'blob' : 'arraybuffer';
- this._responseType = type;
- }
- this._request.responseType = type;
- };
-
- /**
- * Get all the response headers from the XmlHttpRequest.
- *
- * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match
- * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
- * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
- * pair.
- * @method getAllResponseHeaders
- * @return {String}
- * @since 0.4.1
+ * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
+ * the version, so we use capabilities to make a best guess.
+ * @property _xhrLevel
+ * @type {Number}
+ * @default 1
+ * @private
*/
- p.getAllResponseHeaders = function () {
- if (this._request.getAllResponseHeaders instanceof Function) {
- return this._request.getAllResponseHeaders();
- } else {
- return null;
- }
- };
+ this._xhrLevel = 1;
/**
- * Get a specific response header from the XmlHttpRequest.
- *
- * From the docs: Returns the header field value from the response of which the field name matches
- * header, unless the field name is Set-Cookie or Set-Cookie2.
- * @method getResponseHeader
- * @param {String} header The header name to retrieve.
- * @return {String}
- * @since 0.4.1
+ * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
+ * null until the file is loaded.
+ * @property _response
+ * @type {mixed}
+ * @private
*/
- p.getResponseHeader = function (header) {
- if (this._request.getResponseHeader instanceof Function) {
- return this._request.getResponseHeader(header);
- } else {
- return null;
- }
- };
+ this._response = null;
-// protected methods
/**
- * The XHR request has reported progress.
- * @method _handleProgress
- * @param {Object} event The XHR progress event.
+ * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
+ * an HTML tag or a formatted object which is set to the result
property, but the developer may still
+ * want to access the raw content as it was loaded.
+ * @property _rawResponse
+ * @type {String|Object}
* @private
*/
- p._handleProgress = function (event) {
- if (!event || event.loaded > 0 && event.total == 0) {
- return; // Sometimes we get no "total", so just ignore the progress event.
- }
+ this._rawResponse = null;
- var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
- this.dispatchEvent(newEvent);
- };
+ this._canceled = false;
- /**
- * The XHR request has reported a load start.
- * @method _handleLoadStart
- * @param {Object} event The XHR loadStart event.
- * @private
- */
- p._handleLoadStart = function (event) {
- clearTimeout(this._loadTimeout);
- this.dispatchEvent("loadstart");
- };
+ // Setup our event handlers now.
+ this._handleLoadStartProxy = proxy(this._handleLoadStart, this);
+ this._handleProgressProxy = proxy(this._handleProgress, this);
+ this._handleAbortProxy = proxy(this._handleAbort, this);
+ this._handleErrorProxy = proxy(this._handleError, this);
+ this._handleTimeoutProxy = proxy(this._handleTimeout, this);
+ this._handleLoadProxy = proxy(this._handleLoad, this);
+ this._handleReadyStateChangeProxy = proxy(this._handleReadyStateChange, this);
- /**
- * The XHR request has reported an abort event.
- * @method handleAbort
- * @param {Object} event The XHR abort event.
- * @private
- */
- p._handleAbort = function (event) {
- this._clean();
- this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED", null, event));
- };
+ if (!this._createXHR(item)) {
+ //TODO: Throw error?
+ }
+};
- /**
- * The XHR request has reported an error event.
- * @method _handleError
- * @param {Object} event The XHR error event.
- * @private
- */
- p._handleError = function (event) {
- this._clean();
- this.dispatchEvent(new createjs.ErrorEvent(event.message));
- };
+var p = extend(XHRRequest, AbstractRequest);
- /**
- * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
- * event, so we must monitor the readyStateChange to determine if the file is loaded.
- * @method _handleReadyStateChange
- * @param {Object} event The XHR readyStateChange event.
- * @private
- */
- p._handleReadyStateChange = function (event) {
- if (this._request.readyState == 4) {
- this._handleLoad();
- }
- };
+// static properties
+/**
+ * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
+ * @property ACTIVEX_VERSIONS
+ * @type {Array}
+ * @since 0.4.2
+ * @private
+ */
+XHRRequest.ACTIVEX_VERSIONS = [
+ "Msxml2.XMLHTTP.6.0",
+ "Msxml2.XMLHTTP.5.0",
+ "Msxml2.XMLHTTP.4.0",
+ "MSXML2.XMLHTTP.3.0",
+ "MSXML2.XMLHTTP",
+ "Microsoft.XMLHTTP"
+];
- /**
- * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
- * request.readyState == 4
. Only the first call to this method will be processed.
- * @method _handleLoad
- * @param {Object} event The XHR load event.
- * @private
- */
- p._handleLoad = function (event) {
- if (this.loaded) {
- return;
+// Public methods
+/**
+ * Look up the loaded result.
+ * @method getResult
+ * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
+ * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
+ * returned instead.
+ * @return {Object} A result object containing the content that was loaded, such as:
+ *
+ * - An image tag (<image />) for images
+ * - A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the
+ * HTML head.
+ * - A style tag for CSS (<style />)
+ * - Raw text for TEXT
+ * - A formatted JavaScript object defined by JSON
+ * - An XML document
+ * - An binary arraybuffer loaded by XHR
+ *
+ * Note that if a raw result is requested, but not found, the result will be returned instead.
+ */
+p.getResult = function (raw) {
+ if (raw && this._rawResponse) {
+ return this._rawResponse;
+ }
+ return this._response;
+};
+
+// Overrides abstract method in AbstractRequest
+p.cancel = function () {
+ this.canceled = true;
+ this._clean();
+ this._request.abort();
+};
+
+// Overrides abstract method in AbstractLoader
+p.load = function () {
+ if (this._request == null) {
+ this._handleError();
+ return;
+ }
+
+ //Events
+ if (this._request.addEventListener != null) {
+ this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
+ this._request.addEventListener("progress", this._handleProgressProxy, false);
+ this._request.addEventListener("abort", this._handleAbortProxy, false);
+ this._request.addEventListener("error", this._handleErrorProxy, false);
+ this._request.addEventListener("timeout", this._handleTimeoutProxy, false);
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.addEventListener("load", this._handleLoadProxy, false);
+ this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
+ } else {
+ // IE9 support
+ this._request.onloadstart = this._handleLoadStartProxy;
+ this._request.onprogress = this._handleProgressProxy;
+ this._request.onabort = this._handleAbortProxy;
+ this._request.onerror = this._handleErrorProxy;
+ this._request.ontimeout = this._handleTimeoutProxy;
+
+ // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
+ this._request.onload = this._handleLoadProxy;
+ this._request.onreadystatechange = this._handleReadyStateChangeProxy;
+ }
+
+ // Set up a timeout if we don't have XHR2
+ if (this._xhrLevel == 1) {
+ this._loadTimeout = setTimeout(proxy(this._handleTimeout, this), this._item.loadTimeout);
+ }
+
+ // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome
+ try {
+ if (!this._item.values || this._item.method == AbstractLoader.GET) {
+ this._request.send();
+ } else if (this._item.method == AbstractLoader.POST) {
+ this._request.send(RequestUtils.formatQueryString(this._item.values));
}
- this.loaded = true;
+ } catch (error) {
+ this.dispatchEvent(new ErrorEvent("XHR_SEND", null, error));
+ }
+};
+
+p.setResponseType = function (type) {
+ // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
+ if (type === 'blob') {
+ type = window.URL ? 'blob' : 'arraybuffer';
+ this._responseType = type;
+ }
+ this._request.responseType = type;
+};
- var error = this._checkError();
- if (error) {
- this._handleError(error);
- return;
- }
+/**
+ * Get all the response headers from the XmlHttpRequest.
+ *
+ * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match
+ * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
+ * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
+ * pair.
+ * @method getAllResponseHeaders
+ * @return {String}
+ * @since 0.4.1
+ */
+p.getAllResponseHeaders = function () {
+ if (this._request.getAllResponseHeaders instanceof Function) {
+ return this._request.getAllResponseHeaders();
+ } else {
+ return null;
+ }
+};
- this._response = this._getResponse();
- // Convert arraybuffer back to blob
- if (this._responseType === 'arraybuffer') {
- try {
- this._response = new Blob([this._response]);
- } catch (e) {
- // Fallback to use BlobBuilder if Blob constructor is not supported
- // Tested on Android 2.3 ~ 4.2 and iOS5 safari
- window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
- if (e.name === 'TypeError' && window.BlobBuilder) {
- var builder = new BlobBuilder();
- builder.append(this._response);
- this._response = builder.getBlob();
- }
- }
- }
- this._clean();
+/**
+ * Get a specific response header from the XmlHttpRequest.
+ *
+ * From the docs: Returns the header field value from the response of which the field name matches
+ * header, unless the field name is Set-Cookie or Set-Cookie2.
+ * @method getResponseHeader
+ * @param {String} header The header name to retrieve.
+ * @return {String}
+ * @since 0.4.1
+ */
+p.getResponseHeader = function (header) {
+ if (this._request.getResponseHeader instanceof Function) {
+ return this._request.getResponseHeader(header);
+ } else {
+ return null;
+ }
+};
- this.dispatchEvent(new createjs.Event("complete"));
- };
+// protected methods
+/**
+ * The XHR request has reported progress.
+ * @method _handleProgress
+ * @param {Object} event The XHR progress event.
+ * @private
+ */
+p._handleProgress = function (event) {
+ if (!event || event.loaded > 0 && event.total == 0) {
+ return; // Sometimes we get no "total", so just ignore the progress event.
+ }
- /**
- * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout
- * callback.
- * @method _handleTimeout
- * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
- * @private
- */
- p._handleTimeout = function (event) {
- this._clean();
+ var newEvent = new ProgressEvent(event.loaded, event.total);
+ this.dispatchEvent(newEvent);
+};
- this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT", null, event));
- };
+/**
+ * The XHR request has reported a load start.
+ * @method _handleLoadStart
+ * @param {Object} event The XHR loadStart event.
+ * @private
+ */
+p._handleLoadStart = function (event) {
+ clearTimeout(this._loadTimeout);
+ this.dispatchEvent("loadstart");
+};
-// Protected
- /**
- * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
- * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
- * @method _checkError
- * @return {int} If the request status returns an error code.
- * @private
- */
- p._checkError = function () {
- //LM: Probably need additional handlers here, maybe 501
- var status = parseInt(this._request.status);
-
- switch (status) {
- case 404: // Not Found
- case 0: // Not Loaded
- return new Error(status);
- }
- return null;
- };
+/**
+ * The XHR request has reported an abort event.
+ * @method handleAbort
+ * @param {Object} event The XHR abort event.
+ * @private
+ */
+p._handleAbort = function (event) {
+ this._clean();
+ this.dispatchEvent(new ErrorEvent("XHR_ABORTED", null, event));
+};
- /**
- * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
- * in other browsers. If there is no response, the _response
property will remain null.
- * @method _getResponse
- * @private
- */
- p._getResponse = function () {
- if (this._response != null) {
- return this._response;
- }
+/**
+ * The XHR request has reported an error event.
+ * @method _handleError
+ * @param {Object} event The XHR error event.
+ * @private
+ */
+p._handleError = function (event) {
+ this._clean();
+ this.dispatchEvent(new ErrorEvent(event.message));
+};
- if (this._request.response != null) {
- return this._request.response;
- }
+/**
+ * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
+ * event, so we must monitor the readyStateChange to determine if the file is loaded.
+ * @method _handleReadyStateChange
+ * @param {Object} event The XHR readyStateChange event.
+ * @private
+ */
+p._handleReadyStateChange = function (event) {
+ if (this._request.readyState == 4) {
+ this._handleLoad();
+ }
+};
- // Android 2.2 uses .responseText
+/**
+ * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
+ * request.readyState == 4
. Only the first call to this method will be processed.
+ * @method _handleLoad
+ * @param {Object} event The XHR load event.
+ * @private
+ */
+p._handleLoad = function (event) {
+ if (this.loaded) {
+ return;
+ }
+ this.loaded = true;
+
+ var error = this._checkError();
+ if (error) {
+ this._handleError(error);
+ return;
+ }
+
+ this._response = this._getResponse();
+ // Convert arraybuffer back to blob
+ if (this._responseType === 'arraybuffer') {
try {
- if (this._request.responseText != null) {
- return this._request.responseText;
- }
+ this._response = new Blob([this._response]);
} catch (e) {
- }
-
- // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
- try {
- if (this._request.responseXML != null) {
- return this._request.responseXML;
+ // Fallback to use BlobBuilder if Blob constructor is not supported
+ // Tested on Android 2.3 ~ 4.2 and iOS5 safari
+ window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ if (e.name === 'TypeError' && window.BlobBuilder) {
+ var builder = new BlobBuilder();
+ builder.append(this._response);
+ this._response = builder.getBlob();
}
- } catch (e) {
}
+ }
+ this._clean();
- return null;
- };
+ this.dispatchEvent(new Event("complete"));
+};
- /**
- * Create an XHR request. Depending on a number of factors, we get totally different results.
- * - Some browsers get an
XDomainRequest
when loading cross-domain.
- * - XMLHttpRequest are created when available.
- * - ActiveX.XMLHTTP objects are used in older IE browsers.
- * - Text requests override the mime type if possible
- * - Origin headers are sent for crossdomain requests in some browsers.
- * - Binary loads set the response type to "arraybuffer"
- * @method _createXHR
- * @param {Object} item The requested item that is being loaded.
- * @return {Boolean} If an XHR request or equivalent was successfully created.
- * @private
- */
- p._createXHR = function (item) {
- // Check for cross-domain loads. We can't fully support them, but we can try.
- var crossdomain = createjs.RequestUtils.isCrossDomain(item);
- var headers = {};
-
- // Create the request. Fallback to whatever support we have.
- var req = null;
- if (window.XMLHttpRequest) {
- req = new XMLHttpRequest();
- // This is 8 or 9, so use XDomainRequest instead.
- if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
- req = new XDomainRequest();
- }
- } else { // Old IE versions use a different approach
- for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
- var axVersion = s.ACTIVEX_VERSIONS[i];
- try {
- req = new ActiveXObject(axVersion);
- break;
- } catch (e) {
- }
- }
- if (req == null) {
- return false;
- }
- }
-
- // Default to utf-8 for Text requests.
- if (item.mimeType == null && createjs.RequestUtils.isText(item.type)) {
- item.mimeType = "text/plain; charset=utf-8";
- }
+/**
+ * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout
+ * callback.
+ * @method _handleTimeout
+ * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
+ * @private
+ */
+p._handleTimeout = function (event) {
+ this._clean();
- // IE9 doesn't support overrideMimeType(), so we need to check for it.
- if (item.mimeType && req.overrideMimeType) {
- req.overrideMimeType(item.mimeType);
- }
+ this.dispatchEvent(new ErrorEvent("PRELOAD_TIMEOUT", null, event));
+};
- // Determine the XHR level
- this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;
+// Protected
+/**
+ * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
+ * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
+ * @method _checkError
+ * @return {int} If the request status returns an error code.
+ * @private
+ */
+p._checkError = function () {
+ //LM: Probably need additional handlers here, maybe 501
+ var status = parseInt(this._request.status);
+
+ switch (status) {
+ case 404: // Not Found
+ case 0: // Not Loaded
+ return new Error(status);
+ }
+ return null;
+};
- var src = null;
- if (item.method == createjs.AbstractLoader.GET) {
- src = createjs.RequestUtils.buildPath(item.src, item.values);
- } else {
- src = item.src;
- }
+/**
+ * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
+ * in other browsers. If there is no response, the _response
property will remain null.
+ * @method _getResponse
+ * @private
+ */
+p._getResponse = function () {
+ if (this._response != null) {
+ return this._response;
+ }
- // Open the request. Set cross-domain flags if it is supported (XHR level 1 only)
- req.open(item.method || createjs.AbstractLoader.GET, src, true);
+ if (this._request.response != null) {
+ return this._request.response;
+ }
- if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
- headers["Origin"] = location.origin;
+ // Android 2.2 uses .responseText
+ try {
+ if (this._request.responseText != null) {
+ return this._request.responseText;
}
+ } catch (e) {
+ }
- // To send data we need to set the Content-type header)
- if (item.values && item.method == createjs.AbstractLoader.POST) {
- headers["Content-Type"] = "application/x-www-form-urlencoded";
+ // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
+ try {
+ if (this._request.responseXML != null) {
+ return this._request.responseXML;
}
+ } catch (e) {
+ }
- if (!crossdomain && !headers["X-Requested-With"]) {
- headers["X-Requested-With"] = "XMLHttpRequest";
- }
+ return null;
+};
- if (item.headers) {
- for (var n in item.headers) {
- headers[n] = item.headers[n];
+/**
+ * Create an XHR request. Depending on a number of factors, we get totally different results.
+ * - Some browsers get an
XDomainRequest
when loading cross-domain.
+ * - XMLHttpRequest are created when available.
+ * - ActiveX.XMLHTTP objects are used in older IE browsers.
+ * - Text requests override the mime type if possible
+ * - Origin headers are sent for crossdomain requests in some browsers.
+ * - Binary loads set the response type to "arraybuffer"
+ * @method _createXHR
+ * @param {Object} item The requested item that is being loaded.
+ * @return {Boolean} If an XHR request or equivalent was successfully created.
+ * @private
+ */
+p._createXHR = function (item) {
+ // Check for cross-domain loads. We can't fully support them, but we can try.
+ var crossdomain = RequestUtils.isCrossDomain(item);
+ var headers = {};
+
+ // Create the request. Fallback to whatever support we have.
+ var req = null;
+ if (window.XMLHttpRequest) {
+ req = new XMLHttpRequest();
+ // This is 8 or 9, so use XDomainRequest instead.
+ if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
+ req = new XDomainRequest();
+ }
+ } else { // Old IE versions use a different approach
+ for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
+ var axVersion = s.ACTIVEX_VERSIONS[i];
+ try {
+ req = new ActiveXObject(axVersion);
+ break;
+ } catch (e) {
}
}
-
- for (n in headers) {
- req.setRequestHeader(n, headers[n])
+ if (req == null) {
+ return false;
}
-
- if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
- req.withCredentials = item.withCredentials;
+ }
+
+ // Default to utf-8 for Text requests.
+ if (item.mimeType == null && RequestUtils.isText(item.type)) {
+ item.mimeType = "text/plain; charset=utf-8";
+ }
+
+ // IE9 doesn't support overrideMimeType(), so we need to check for it.
+ if (item.mimeType && req.overrideMimeType) {
+ req.overrideMimeType(item.mimeType);
+ }
+
+ // Determine the XHR level
+ this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;
+
+ var src = null;
+ if (item.method == AbstractLoader.GET) {
+ src = RequestUtils.buildPath(item.src, item.values);
+ } else {
+ src = item.src;
+ }
+
+ // Open the request. Set cross-domain flags if it is supported (XHR level 1 only)
+ req.open(item.method || AbstractLoader.GET, src, true);
+
+ if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
+ headers["Origin"] = location.origin;
+ }
+
+ // To send data we need to set the Content-type header)
+ if (item.values && item.method == AbstractLoader.POST) {
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+
+ if (!crossdomain && !headers["X-Requested-With"]) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ if (item.headers) {
+ for (var n in item.headers) {
+ headers[n] = item.headers[n];
}
+ }
- this._request = req;
-
- return true;
- };
+ for (n in headers) {
+ req.setRequestHeader(n, headers[n])
+ }
- /**
- * A request has completed (or failed or canceled), and needs to be disposed.
- * @method _clean
- * @private
- */
- p._clean = function () {
- clearTimeout(this._loadTimeout);
-
- if (this._request.removeEventListener != null) {
- this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
- this._request.removeEventListener("progress", this._handleProgressProxy);
- this._request.removeEventListener("abort", this._handleAbortProxy);
- this._request.removeEventListener("error", this._handleErrorProxy);
- this._request.removeEventListener("timeout", this._handleTimeoutProxy);
- this._request.removeEventListener("load", this._handleLoadProxy);
- this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
- } else {
- this._request.onloadstart = null;
- this._request.onprogress = null;
- this._request.onabort = null;
- this._request.onerror = null;
- this._request.ontimeout = null;
- this._request.onload = null;
- this._request.onreadystatechange = null;
- }
- };
+ if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
+ req.withCredentials = item.withCredentials;
+ }
- p.toString = function () {
- return "[PreloadJS XHRRequest]";
- };
+ this._request = req;
- createjs.XHRRequest = createjs.promote(XHRRequest, "AbstractRequest");
+ return true;
+};
-}());
+/**
+ * A request has completed (or failed or canceled), and needs to be disposed.
+ * @method _clean
+ * @private
+ */
+p._clean = function () {
+ clearTimeout(this._loadTimeout);
+
+ if (this._request.removeEventListener != null) {
+ this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
+ this._request.removeEventListener("progress", this._handleProgressProxy);
+ this._request.removeEventListener("abort", this._handleAbortProxy);
+ this._request.removeEventListener("error", this._handleErrorProxy);
+ this._request.removeEventListener("timeout", this._handleTimeoutProxy);
+ this._request.removeEventListener("load", this._handleLoadProxy);
+ this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
+ } else {
+ this._request.onloadstart = null;
+ this._request.onprogress = null;
+ this._request.onabort = null;
+ this._request.onerror = null;
+ this._request.ontimeout = null;
+ this._request.onload = null;
+ this._request.onreadystatechange = null;
+ }
+};
+
+p.toString = function () {
+ return "[PreloadJS XHRRequest]";
+};
+
+module.exports = XHRRequest = promote(XHRRequest, "AbstractRequest");
diff --git a/src/preloadjs/utils/DataUtils.js b/src/preloadjs/utils/DataUtils.js
index b461098..9ff8dca 100644
--- a/src/preloadjs/utils/DataUtils.js
+++ b/src/preloadjs/utils/DataUtils.js
@@ -31,7 +31,11 @@
* @module PreloadJS
*/
-(function () {
+
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
/**
* A few data utilities for formatting different data types.
@@ -97,4 +101,4 @@
createjs.DataUtils = s;
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/utils/DomUtils.js b/src/preloadjs/utils/DomUtils.js
index 9480588..1915647 100644
--- a/src/preloadjs/utils/DomUtils.js
+++ b/src/preloadjs/utils/DomUtils.js
@@ -31,7 +31,10 @@
* @module PreloadJS
*/
-(function () {
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
+
+(function (createjs) {
/**
* A few utilities for interacting with the dom.
@@ -53,4 +56,4 @@
createjs.DomUtils = s;
-}());
+}(scope.createjs));
diff --git a/src/preloadjs/utils/RequestUtils.js b/src/preloadjs/utils/RequestUtils.js
index 072a26e..ca8f6bc 100644
--- a/src/preloadjs/utils/RequestUtils.js
+++ b/src/preloadjs/utils/RequestUtils.js
@@ -31,294 +31,296 @@
* @module PreloadJS
*/
-(function () {
- /**
- * Utilities that assist with parsing load items, and determining file types, etc.
- * @class RequestUtils
- */
- var s = {};
+var AbstractLoader = require('../loaders/AbstractLoader');
- /**
- * The Regular Expression used to test file URLS for an absolute path.
- * @property ABSOLUTE_PATH
- * @type {RegExp}
- * @static
- */
- s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
-
- /**
- * The Regular Expression used to test file URLS for a relative path.
- * @property RELATIVE_PATH
- * @type {RegExp}
- * @static
- */
- s.RELATIVE_PATT = (/^[./]*?\//i);
+/**
+ * Utilities that assist with parsing load items, and determining file types, etc.
+ * @class RequestUtils
+ */
+var s = {};
- /**
- * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
- * removed.
- * @property EXTENSION_PATT
- * @type {RegExp}
- * @static
- */
- s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
+/**
+ * The Regular Expression used to test file URLS for an absolute path.
+ * @property ABSOLUTE_PATH
+ * @type {RegExp}
+ * @static
+ */
+s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
- /**
- * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
- *
- * - If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
- * `//networkPath`)
- * - If the path is relative. Relative paths start with `../` or `/path` (or similar)
- * - The file extension. This is determined by the filename with an extension. Query strings are dropped, and
- * the file path is expected to follow the format `name.ext`.
- *
- * @method parseURI
- * @param {String} path
- * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
- * property, which is the lowercase extension.
- * @static
- */
- s.parseURI = function (path) {
- var info = {absolute: false, relative: false};
- if (path == null) { return info; }
+/**
+ * The Regular Expression used to test file URLS for a relative path.
+ * @property RELATIVE_PATH
+ * @type {RegExp}
+ * @static
+ */
+s.RELATIVE_PATT = (/^[./]*?\//i);
- // Drop the query string
- var queryIndex = path.indexOf("?");
- if (queryIndex > -1) {
- path = path.substr(0, queryIndex);
- }
+/**
+ * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
+ * removed.
+ * @property EXTENSION_PATT
+ * @type {RegExp}
+ * @static
+ */
+s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
- // Absolute
- var match;
- if (s.ABSOLUTE_PATT.test(path)) {
- info.absolute = true;
+/**
+ * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
+ *
+ * - If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
+ * `//networkPath`)
+ * - If the path is relative. Relative paths start with `../` or `/path` (or similar)
+ * - The file extension. This is determined by the filename with an extension. Query strings are dropped, and
+ * the file path is expected to follow the format `name.ext`.
+ *
+ * @method parseURI
+ * @param {String} path
+ * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
+ * property, which is the lowercase extension.
+ * @static
+ */
+s.parseURI = function (path) {
+ var info = {absolute: false, relative: false};
+ if (path == null) {
+ return info;
+ }
- // Relative
- } else if (s.RELATIVE_PATT.test(path)) {
- info.relative = true;
- }
+ // Drop the query string
+ var queryIndex = path.indexOf("?");
+ if (queryIndex > -1) {
+ path = path.substr(0, queryIndex);
+ }
- // Extension
- if (match = path.match(s.EXTENSION_PATT)) {
- info.extension = match[1].toLowerCase();
- }
- return info;
- };
+ // Absolute
+ var match;
+ if (s.ABSOLUTE_PATT.test(path)) {
+ info.absolute = true;
- /**
- * Formats an object into a query string for either a POST or GET request.
- * @method formatQueryString
- * @param {Object} data The data to convert to a query string.
- * @param {Array} [query] Existing name/value pairs to append on to this query.
- * @static
- */
- s.formatQueryString = function (data, query) {
- if (data == null) {
- throw new Error('You must specify data.');
- }
- var params = [];
- for (var n in data) {
- params.push(n + '=' + escape(data[n]));
- }
- if (query) {
- params = params.concat(query);
- }
- return params.join('&');
- };
+ // Relative
+ } else if (s.RELATIVE_PATT.test(path)) {
+ info.relative = true;
+ }
- /**
- * A utility method that builds a file path using a source and a data object, and formats it into a new path.
- * @method buildPath
- * @param {String} src The source path to add values to.
- * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
- * path will be preserved.
- * @returns {string} A formatted string that contains the path and the supplied parameters.
- * @static
- */
- s.buildPath = function (src, data) {
- if (data == null) {
- return src;
- }
+ // Extension
+ if (match = path.match(s.EXTENSION_PATT)) {
+ info.extension = match[1].toLowerCase();
+ }
+ return info;
+};
- var query = [];
- var idx = src.indexOf('?');
+/**
+ * Formats an object into a query string for either a POST or GET request.
+ * @method formatQueryString
+ * @param {Object} data The data to convert to a query string.
+ * @param {Array} [query] Existing name/value pairs to append on to this query.
+ * @static
+ */
+s.formatQueryString = function (data, query) {
+ if (data == null) {
+ throw new Error('You must specify data.');
+ }
+ var params = [];
+ for (var n in data) {
+ params.push(n + '=' + escape(data[n]));
+ }
+ if (query) {
+ params = params.concat(query);
+ }
+ return params.join('&');
+};
- if (idx != -1) {
- var q = src.slice(idx + 1);
- query = query.concat(q.split('&'));
- }
+/**
+ * A utility method that builds a file path using a source and a data object, and formats it into a new path.
+ * @method buildPath
+ * @param {String} src The source path to add values to.
+ * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
+ * path will be preserved.
+ * @returns {string} A formatted string that contains the path and the supplied parameters.
+ * @static
+ */
+s.buildPath = function (src, data) {
+ if (data == null) {
+ return src;
+ }
- if (idx != -1) {
- return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
- } else {
- return src + '?' + this._formatQueryString(data, query);
- }
- };
+ var query = [];
+ var idx = src.indexOf('?');
- /**
- * @method isCrossDomain
- * @param {LoadItem|Object} item A load item with a `src` property.
- * @return {Boolean} If the load item is loading from a different domain than the current location.
- * @static
- */
- s.isCrossDomain = function (item) {
- var target = document.createElement("a");
- target.href = item.src;
+ if (idx != -1) {
+ var q = src.slice(idx + 1);
+ query = query.concat(q.split('&'));
+ }
- var host = document.createElement("a");
- host.href = location.href;
+ if (idx != -1) {
+ return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
+ } else {
+ return src + '?' + this._formatQueryString(data, query);
+ }
+};
- var crossdomain = (target.hostname != "") &&
- (target.port != host.port ||
- target.protocol != host.protocol ||
- target.hostname != host.hostname);
- return crossdomain;
- };
+/**
+ * @method isCrossDomain
+ * @param {LoadItem|Object} item A load item with a `src` property.
+ * @return {Boolean} If the load item is loading from a different domain than the current location.
+ * @static
+ */
+s.isCrossDomain = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
- /**
- * @method isLocal
- * @param {LoadItem|Object} item A load item with a `src` property
- * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
- * well.
- * @static
- */
- s.isLocal = function (item) {
- var target = document.createElement("a");
- target.href = item.src;
- return target.hostname == "" && target.protocol == "file:";
- };
+ var host = document.createElement("a");
+ host.href = location.href;
- /**
- * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
- * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play
- * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
- * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
- * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
- * @method isBinary
- * @param {String} type The item type.
- * @return {Boolean} If the specified type is binary.
- * @static
- */
- s.isBinary = function (type) {
- switch (type) {
- case createjs.AbstractLoader.IMAGE:
- case createjs.AbstractLoader.BINARY:
- return true;
- default:
- return false;
- }
- };
+ var crossdomain = (target.hostname != "") &&
+ (target.port != host.port ||
+ target.protocol != host.protocol ||
+ target.hostname != host.hostname);
+ return crossdomain;
+};
- /**
- * Check if item is a valid HTMLImageElement
- * @method isImageTag
- * @param {Object} item
- * @returns {Boolean}
- * @static
- */
- s.isImageTag = function(item) {
- return item instanceof HTMLImageElement;
- };
+/**
+ * @method isLocal
+ * @param {LoadItem|Object} item A load item with a `src` property
+ * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
+ * well.
+ * @static
+ */
+s.isLocal = function (item) {
+ var target = document.createElement("a");
+ target.href = item.src;
+ return target.hostname == "" && target.protocol == "file:";
+};
- /**
- * Check if item is a valid HTMLAudioElement
- * @method isAudioTag
- * @param {Object} item
- * @returns {Boolean}
- * @static
- */
- s.isAudioTag = function(item) {
- if (window.HTMLAudioElement) {
- return item instanceof HTMLAudioElement;
- } else {
+/**
+ * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
+ * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play
+ * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
+ * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
+ * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
+ * @method isBinary
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is binary.
+ * @static
+ */
+s.isBinary = function (type) {
+ switch (type) {
+ case AbstractLoader.IMAGE:
+ case AbstractLoader.BINARY:
+ return true;
+ default:
return false;
- }
- };
+ }
+};
- /**
- * Check if item is a valid HTMLVideoElement
- * @method isVideoTag
- * @param {Object} item
- * @returns {Boolean}
- * @static
- */
- s.isVideoTag = function(item) {
- if (window.HTMLVideoElement) {
- return item instanceof HTMLVideoElement;
- } else {
- return false;
- }
- };
+/**
+ * Check if item is a valid HTMLImageElement
+ * @method isImageTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isImageTag = function (item) {
+ return item instanceof HTMLImageElement;
+};
+
+/**
+ * Check if item is a valid HTMLAudioElement
+ * @method isAudioTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isAudioTag = function (item) {
+ if (window.HTMLAudioElement) {
+ return item instanceof HTMLAudioElement;
+ } else {
+ return false;
+ }
+};
- /**
- * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
- * @method isText
- * @param {String} type The item type.
- * @return {Boolean} If the specified type is text.
- * @static
- */
- s.isText = function (type) {
- switch (type) {
- case createjs.AbstractLoader.TEXT:
- case createjs.AbstractLoader.JSON:
- case createjs.AbstractLoader.MANIFEST:
- case createjs.AbstractLoader.XML:
- case createjs.AbstractLoader.CSS:
- case createjs.AbstractLoader.SVG:
- case createjs.AbstractLoader.JAVASCRIPT:
- case createjs.AbstractLoader.SPRITESHEET:
- return true;
- default:
- return false;
- }
- };
+/**
+ * Check if item is a valid HTMLVideoElement
+ * @method isVideoTag
+ * @param {Object} item
+ * @returns {Boolean}
+ * @static
+ */
+s.isVideoTag = function (item) {
+ if (window.HTMLVideoElement) {
+ return item instanceof HTMLVideoElement;
+ } else {
+ return false;
+ }
+};
- /**
- * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
- * if it is an unusual extension.
- * @method getTypeByExtension
- * @param {String} extension The file extension to use to determine the load type.
- * @return {String} The determined load type (for example, AbstractLoader.IMAGE
). Will return `null` if
- * the type can not be determined by the extension.
- * @static
- */
- s.getTypeByExtension = function (extension) {
- if (extension == null) {
- return createjs.AbstractLoader.TEXT;
- }
+/**
+ * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
+ * @method isText
+ * @param {String} type The item type.
+ * @return {Boolean} If the specified type is text.
+ * @static
+ */
+s.isText = function (type) {
+ switch (type) {
+ case AbstractLoader.TEXT:
+ case AbstractLoader.JSON:
+ case AbstractLoader.MANIFEST:
+ case AbstractLoader.XML:
+ case AbstractLoader.CSS:
+ case AbstractLoader.SVG:
+ case AbstractLoader.JAVASCRIPT:
+ case AbstractLoader.SPRITESHEET:
+ return true;
+ default:
+ return false;
+ }
+};
- switch (extension.toLowerCase()) {
- case "jpeg":
- case "jpg":
- case "gif":
- case "png":
- case "webp":
- case "bmp":
- return createjs.AbstractLoader.IMAGE;
- case "ogg":
- case "mp3":
- case "webm":
- return createjs.AbstractLoader.SOUND;
- case "mp4":
- case "webm":
- case "ts":
- return createjs.AbstractLoader.VIDEO;
- case "json":
- return createjs.AbstractLoader.JSON;
- case "xml":
- return createjs.AbstractLoader.XML;
- case "css":
- return createjs.AbstractLoader.CSS;
- case "js":
- return createjs.AbstractLoader.JAVASCRIPT;
- case 'svg':
- return createjs.AbstractLoader.SVG;
- default:
- return createjs.AbstractLoader.TEXT;
- }
- };
+/**
+ * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
+ * if it is an unusual extension.
+ * @method getTypeByExtension
+ * @param {String} extension The file extension to use to determine the load type.
+ * @return {String} The determined load type (for example, AbstractLoader.IMAGE
). Will return `null` if
+ * the type can not be determined by the extension.
+ * @static
+ */
+s.getTypeByExtension = function (extension) {
+ if (extension == null) {
+ return AbstractLoader.TEXT;
+ }
- createjs.RequestUtils = s;
+ switch (extension.toLowerCase()) {
+ case "jpeg":
+ case "jpg":
+ case "gif":
+ case "png":
+ case "webp":
+ case "bmp":
+ return AbstractLoader.IMAGE;
+ case "ogg":
+ case "mp3":
+ case "webm":
+ return AbstractLoader.SOUND;
+ case "mp4":
+ case "webm":
+ case "ts":
+ return AbstractLoader.VIDEO;
+ case "json":
+ return AbstractLoader.JSON;
+ case "xml":
+ return AbstractLoader.XML;
+ case "css":
+ return AbstractLoader.CSS;
+ case "js":
+ return AbstractLoader.JAVASCRIPT;
+ case 'svg':
+ return AbstractLoader.SVG;
+ default:
+ return AbstractLoader.TEXT;
+ }
+};
-}());
+var RequestUtils = s;
+module.exports = RequestUtils;
diff --git a/src/preloadjs/version.js b/src/preloadjs/version.js
index 93bc877..2141e2e 100644
--- a/src/preloadjs/version.js
+++ b/src/preloadjs/version.js
@@ -1,6 +1,7 @@
-this.createjs = this.createjs || {};
+var scope = (typeof window == 'undefined')?this:window;
+scope.createjs = scope.createjs || {};
-(function () {
+(function (createjs) {
"use strict";
/**
@@ -25,4 +26,4 @@ this.createjs = this.createjs || {};
**/
s.buildDate = /*=date*/""; // injected by build process
-})();
+})(scope.createjs);