this.createjs = this.createjs||{}; (function() { "use strict"; /** * Static class holding library specific information such as the version and buildDate of * the library. * * The old PreloadJS class has been renamed to LoadQueue. Please see the {{#crossLink "LoadQueue"}}{{/crossLink}} * class for information on loading files. * @class PreloadJS **/ var s = createjs.PreloadJS = createjs.PreloadJS || {}; /** * The version string for this release. * @property version * @type String * @static **/ s.version = /*version*/"NEXT"; // injected by build process /** * The build date for this release in UTC format. * @property buildDate * @type String * @static **/ s.buildDate = /*date*/"Wed, 20 Nov 2013 16:17:10 GMT"; // injected by build process })(); /* * 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 * files of each library and are available on the createsjs namespace directly. * *
complete
event.
* @property loaded
* @type {Boolean}
* @default false
*/
p.loaded = false;
/**
* Determine if the loader was canceled. Canceled loads will not fire complete events. Note that
* {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "AbstractLoader/close"}}{{/crossLink}}
* instead of canceled.
* @property canceled
* @type {Boolean}
* @default false
*/
p.canceled = false;
/**
* The current load progress (percentage) for this item. This will be a number between 0 and 1.
* @property progress
* @type {Number}
* @default 0
*/
p.progress = 0;
/**
* The item this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}}, but will
* be available on loaders such as {{#crossLink "XHRLoader"}}{{/crossLink}} and {{#crossLink "TagLoader"}}{{/crossLink}}.
* @property _item
* @type {Object}
* @private
*/
p._item = null;
/**
* A path that will be prepended on to the item's source parameter before it is loaded.
* @property _basePath
* @type {String}
* @private
* @since 0.3.1
*/
p._basePath = null;
// Events
/**
* The event that is fired when the overall progress changes.
* @event progress
* @param {Object} target The object that dispatched the event.
* @param {String} type The event type.
* @param {Number} loaded The amount that has been loaded so far. Note that this is may just be a percentage of 1,
* since file sizes can not be determined before a load is kicked off, if at all.
* @param {Number} total The total number of bytes. Note that this may just be 1.
* @param {Number} progress The ratio that has been loaded between 0 and 1.
* @since 0.3.0
*/
/**
* The event 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 event 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 event 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. There may be additional properties such as the error reason on event
* objects.
* @event error
* @param {Object} target The object that dispatched the event.
* @param {String} type The event type.
* @param {Object} [item] The item that was being loaded that caused the error. The item 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.
* @param {String} [error] The error object or text.
* @since 0.3.0
*/
//TODO: Deprecated
/**
* REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}
* event.
* @property onProgress
* @type {Function}
* @deprecated Use addEventListener and the "progress" event.
*/
/**
* REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
* event.
* @property onLoadStart
* @type {Function}
* @deprecated Use addEventListener and the "loadstart" event.
*/
/**
* REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
* event.
* @property onComplete
* @type {Function}
* @deprecated Use addEventListener and the "complete" event.
*/
/**
* REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
* event.
* @property onError
* @type {Function}
* @deprecated Use addEventListener and the "error" event.
*/
// mix-ins:
// EventDispatcher methods:
p.addEventListener = null;
p.removeEventListener = null;
p.removeAllEventListeners = null;
p.dispatchEvent = null;
p.hasEventListener = null;
p._listeners = null;
createjs.EventDispatcher.initialize(p);
/**
* Get a reference to the manifest item that is loaded by this loader. In most 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 an Object created by the LoadQueue.
* @return {Object} The manifest item that this loader is responsible for loading.
*/
p.getItem = function() {
return this._item;
};
/**
* Initialize the loader. This is called by the constructor.
* @method init
* @private
*/
p.init = function () {};
/**
* Begin loading the queued items. This method can be called when a {{#crossLink "LoadQueue"}}{{/crossLink}} is set
* up but not started immediately.
* @example
* var queue = new createjs.LoadQueue();
* queue.addEventListener("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() {};
/**
* 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() {};
//Callback proxies
/**
* Dispatch a loadstart event. 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 progress event. Please see the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} event for
* details on the event payload.
* @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.Event("progress");
event.loaded = this.progress;
event.total = 1;
} else {
event = value;
this.progress = value.loaded / value.total;
if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
}
event.progress = this.progress;
this.hasEventListener("progress") && this.dispatchEvent(event);
};
/**
* Dispatch a complete event. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
* for details on the event payload.
* @method _sendComplete
* @protected
*/
p._sendComplete = function() {
if (this._isCanceled()) { return; }
this.dispatchEvent("complete");
};
/**
* Dispatch an error event. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} event for
* details on the event payload.
* @method _sendError
* @param {Object} 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.Event("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;
};
/**
* Parse a file URI using the AbstractLoader.FILE_PATTERN
RegExp pattern.
* @method _parseURI
* @param {String} path The file path to parse.
* @return {Array} The matched file contents. Please see the AbstractLoader.FILE_PATTERN
property for
* details on the return value. This will return null if it does not match.
* @protected
*/
p._parseURI = function(path) {
if (!path) { return null; }
return path.match(s.FILE_PATTERN);
};
/**
* 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.
* @private
*/
p._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, a basePath, and a data object, and formats it into a new
* path. All of the loaders in PreloadJS use this method to compile paths when loading.
* @method buildPath
* @param {String} src The source path to add values to.
* @param {String} [basePath] A string to prepend to the file path. Sources beginning with http:// or similar will
* not receive a base path.
* @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.
* @since 0.3.1
*/
p.buildPath = function(src, _basePath, data) {
if (_basePath != null) {
var match = this._parseURI(src);
// IE 7,8 Return empty string here.
if (match == null || match[1] == null || match[1] == '') {
src = _basePath + src;
}
}
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 toString
* @return {String} a string representation of the instance.
*/
p.toString = function() {
return "[PreloadJS AbstractLoader]";
};
createjs.AbstractLoader = AbstractLoader;
}());
/*
* 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.
*
* false
as the second parameter, the queue will not immediately load the files (unless 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.
*
* queue.load();
*
* File Typestype
property with any manifest item.
*
* queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.LoadQueue.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.LoadQueue.IMAGE});
*
* Supported types include:
* rawResult
property of the fileload
event,
* or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, and true
as the 2nd
* parameter. This is only applicable for content that has been parsed for the browser, specifically, JavaScript,
* CSS, XML, SVG, and JSON objects.
*
* var image = queue.getResult("image", true);
*
* PluginscanPlayThrough
event is fired. Browsers other
* than Chrome will continue to download in the background.false
, LoadQueue 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 http:// or similar will not receive a base path.
* Note that a basePath provided to any loadFile or loadManifest call will override the
* basePath specified on the LoadQueue constructor.
* @constructor
* @extends AbstractLoader
*/
var LoadQueue = function(useXHR, basePath) {
this.init(useXHR, basePath);
};
var p = LoadQueue.prototype = new createjs.AbstractLoader();
var s = LoadQueue;
/**
* Time in milliseconds to assume a load has failed.
* @property LOAD_TIMEOUT
* @type {Number}
* @default 8000
* @static
*/
s.LOAD_TIMEOUT = 8000;
// Preload Types
/**
* The preload type for generic binary types. Note that images and sound files are treated as binary.
* @property BINARY
* @type {String}
* @default binary
* @static
*/
s.BINARY = "binary";
/**
* The preload type for css files. CSS files are loaded into a LINK or STYLE tag (depending on the load type)
* @property CSS
* @type {String}
* @default css
* @static
*/
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
*/
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 were injected.
* @property JAVASCRIPT
* @type {String}
* @default javascript
* @static
*/
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/useXHR:property"}}{{/crossLink}} property is set to.
* @property JSON
* @type {String}
* @default json
* @static
*/
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/useXHR:property"}}{{/crossLink}}
* property is set to.
* @property JSONP
* @type {String}
* @default jsonp
* @static
*/
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, and parsed. 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/useXHR:property"}}{{/crossLink}} property is set to.
* @property MANIFEST
* @type {String}
* @default manifest
* @static
* @since 0.4.1
*/
s.MANIFEST = "manifest";
/**
* The preload type for sound files, usually mp3, ogg, or wav. Audio is loaded into an AUDIO tag.
* @property SOUND
* @type {String}
* @default sound
* @static
*/
s.SOUND = "sound";
/**
* The preload type for SVG files.
* @property SVG
* @type {String}
* @default svg
* @static
*/
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
*/
s.TEXT = "text";
/**
* The preload type for xml files. XML is loaded into an XML document.
* @property XML
* @type {String}
* @default xml
* @static
*/
s.XML = "xml";
/**
* Defines a POST request, use for a method value when loading data.
*
* @type {string}
*/
s.POST = 'POST';
/**
* Defines a GET request, use for a method value when loading data.
*
* @type {string}
*/
s.GET = 'GET';
// Prototype
/**
* 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 WebAudio can not be
* loaded with tags, so it will default the the correct type instead of using the user-defined type.
*
* Note: This property is read-only. To change it, please use the {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}}
* method, or specify the `useXHR` argument in the LoadQueue constructor.
*
* @property useXHR
* @type {Boolean}
* @readOnly
* @default true
*/
p.useXHR = true;
/**
* Determines if the LoadQueue will stop processing the current queue when an error is encountered.
* @property stopOnError
* @type {Boolean}
* @default false
*/
p.stopOnError = false;
/**
* Ensure loaded scripts "complete" in the order they are specified. Note that scripts loaded via tags will only
* load one at a time, and will be added to the document when they are loaded.
* @property maintainScriptOrder
* @type {Boolean}
* @default true
*/
p.maintainScriptOrder = true;
/**
* 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
*/
p.next = null;
// 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 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 event is fired when an an individual file progress changes.
* @event fileprogress
* @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.
* @param {Number} loaded The number of bytes that have been loaded. Note that this may just be a percentage of 1.
* @param {Number} total The total number of bytes. If it is unknown, the value is 1.
* @param {Number} progress The amount that has been loaded between 0 and 1.
* @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.
*/
//TODO: Deprecated
/**
* REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
* event.
* @property onFileLoad
* @type {Function}
* @deprecated Use addEventListener and the "fileload" event.
*/
/**
* REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
* event.
* @property onFileProgress
* @type {Function}
* @deprecated Use addEventListener and the "fileprogress" event.
*/
// Protected
/**
* 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._typeCallbacks = null;
/**
* 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
*/
p._extensionCallbacks = null;
/**
* 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
*/
p._loadStartWasDispatched = 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
*/
p._maxConnections = 1;
/**
* 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
*/
p._currentlyLoadingScript = null;
/**
* An array containing the currently downloading files.
* @property _currentLoads
* @type {Array}
* @private
*/
p._currentLoads = null;
/**
* An array containing the queued items that have not yet started downloading.
* @property _loadQueue
* @type {Array}
* @private
*/
p._loadQueue = null;
/**
* An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
* @property _loadQueueBackup
* @type {Array}
* @private
*/
p._loadQueueBackup = null;
/**
* An object hash of items that have finished downloading, indexed by item IDs.
* @property _loadItemsById
* @type {Object}
* @private
*/
p._loadItemsById = null;
/**
* An object hash of items that have finished downloading, indexed by item source.
* @property _loadItemsBySrc
* @type {Object}
* @private
*/
p._loadItemsBySrc = null;
/**
* An object hash of loaded items, indexed by the ID of the load item.
* @property _loadedResults
* @type {Object}
* @private
*/
p._loadedResults = null;
/**
* An object hash of un-parsed loaded items, indexed by the ID of the load item.
* @property _loadedRawResults
* @type {Object}
* @private
*/
p._loadedRawResults = null;
/**
* 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.
* @property _numItems
* @type {Number}
* @default 0
* @private
*/
p._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
*/
p._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
*/
p._scriptOrder = null;
/**
* 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._loadedScripts = null;
// Overrides abstract method in AbstractLoader
p.init = function(useXHR, basePath) {
this._numItems = this._numItemsLoaded = 0;
this._paused = false;
this._loadStartWasDispatched = false;
this._currentLoads = [];
this._loadQueue = [];
this._loadQueueBackup = [];
this._scriptOrder = [];
this._loadedScripts = [];
this._loadItemsById = {};
this._loadItemsBySrc = {};
this._loadedResults = {};
this._loadedRawResults = {};
// Callbacks for plugins
this._typeCallbacks = {};
this._extensionCallbacks = {};
this._basePath = basePath;
this.setUseXHR(useXHR);
};
/**
* Change the usXHR value. Note that if this is set to true, it may fail depending on the browser's capabilities.
* @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
*/
p.setUseXHR = 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.useXHR = (value != false && window.XMLHttpRequest != null);
return this.useXHR;
};
/**
* 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. Items that have not yet started can be kicked off again using
* the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method.
* @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).
* @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 && !(idsOrUrls instanceof Array)) {
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.useXHR);
// 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) {
delete this._loadItemsById[r.id];
delete this._loadItemsBySrc[r.src];
this._disposeItem(r);
} 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; inot 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.
* @method isBinary
* @param {String} type The item type.
* @return If the specified type is binary.
* @private
*/
s.isBinary = function(type) {
switch (type) {
case createjs.LoadQueue.IMAGE:
case createjs.LoadQueue.BINARY:
return true;
default:
return 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 || plugin.getPreloadHandlers == null) { return; }
var map = plugin.getPreloadHandlers();
map.scope = plugin;
if (map.types != null) {
for (var i=0, l=map.types.length; i 0) {
this._loadNext();
}
}
/**
* Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
* method.
*
* Note that 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 {Object | String} file The file object or path to load. A file can be either
*
* - a path to a resource (string). Note that this kind of load item will be
* converted to an object (see below) in the background.
* - OR an object that contains:
* - src: 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.
* - type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection
* of types using the extension. Supported types are defined on LoadQueue, such as
LoadQueue.IMAGE
.
* It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
* - id: A string identifier which can be used to reference the loaded object.
* - callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
* - data: An arbitrary data object, which is included with the loaded object
* - method: used to define if this request uses GET or POST when sending data to the server. Default; GET
* - values: Optional object of name/value pairs to send to the server.
*
*
* @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] An optional base path prepended to the file source when the file is loaded.
* Sources beginning with http:// or similar will not receive a base path.
* The load item will not be modified.
*/
p.loadFile = function(file, loadNow, basePath) {
if (file == null) {
var event = new createjs.Event("error");
event.text = "PRELOAD_NO_FILE";
this._sendError(event);
return;
}
this._addItem(file, basePath);
if (loadNow !== false) {
this.setPaused(false);
} else {
this.setPaused(true);
}
}
/**
* Load an array of items. 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).
*
* Note that 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 The list of files to load. If a single object or string is passed, it will
* be loaded the same as a single-item array. Each load item can be either:
*
* - a path to a resource (string). Note that this kind of load item will be
* converted to an object (see below) in the background.
* - OR an object that contains:
* - src: 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.
* - type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection
* of types using the extension. Supported types are defined on LoadQueue, such as
LoadQueue.IMAGE
.
* It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
* - id: A string identifier which can be used to reference the loaded object.
* - data: An arbitrary data object, which is returned with the loaded object
*
*
* @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] An optional base path prepended to each of the files' source when the file is loaded.
* Sources beginning with http:// or similar will not receive a base path.
* The load items will not be modified.
*/
p.loadManifest = function(manifest, loadNow, basePath) {
var data = null;
// Proper list of items
if (manifest instanceof Array) {
if (manifest.length == 0) {
var event = new createjs.Event("error");
event.text = "PRELOAD_MANIFEST_EMPTY";
this._sendError(event);
return;
}
data = manifest;
} else {
// Empty/null
if (manifest == null) {
var event = new createjs.Event("error");
event.text = "PRELOAD_MANIFEST_NULL";
this._sendError(event);
return;
}
data = [manifest];
}
for (var i=0, l=data.length; iid
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 "fileload" 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.
* @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:
* 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;iLoadQueue.fileprogress
* event for details on the event payload.
* @method _sendFileProgress
* @param {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._cleanUp();
return;
}
if (!this.hasEventListener("fileprogress")) { return; }
var event = new createjs.Event("fileprogress");
event.progress = progress;
event.loaded = progress;
event.total = 1;
event.item = item;
this.dispatchEvent(event);
};
/**
* Dispatch a fileload event. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
* details on the event payload.
* @method _sendFileComplete
* @param {Object} item The item that is being loaded.
* @param {TagLoader | XHRLoader} loader
* @protected
*/
p._sendFileComplete = function(item, loader) {
if (this._isCanceled()) { 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 event 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 {TagLoader | XHRLoader} loader
* @protected
*/
p._sendFileStart = function(item) {
var event = new createjs.Event("filestart");
event.item = item;
this.hasEventListener("filestart") && this.dispatchEvent(event);
};
/**
* REMOVED. Use createjs.proxy instead
* @method proxy
* @param {Function} method The function to call
* @param {Object} scope The scope to call the method name on
* @static
* @private
* @deprecated In favour of the createjs.proxy method (see LoadQueue source).
*/
p.toString = function() {
return "[PreloadJS LoadQueue]";
};
createjs.LoadQueue = LoadQueue;
// Helper methods
// An additional module to determine the current browser, version, operating system, and other environmental variables.
var BrowserDetect = function() {}
BrowserDetect.init = function() {
var agent = navigator.userAgent;
BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1);
BrowserDetect.isOpera = (window.opera != null);
BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1);
BrowserDetect.isIOS = agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1;
}
BrowserDetect.init();
createjs.LoadQueue.BrowserDetect = BrowserDetect;
}());
/*
* TagLoader
* 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:
this.createjs = this.createjs||{};
(function() {
"use strict";
/**
* A preloader that loads items using a tag-based approach. HTML audio and images can use this loader to load
* content cross-domain without security errors, whereas anything loaded with XHR has potential issues with cross-
* domain requests.
*
* Note for audio tags, TagLoader relies on the canPlayThrough
event, which fires when the buffer
* is full enough to play the audio all the way through at the current download speed. This completely preloads most
* sound effects, however longer tracks like background audio will only load a portion before the event is fired.
* Most browsers (all excluding Chrome) will continue to preload once this is fired, so this is considered good
* enough for most cases.
* @class TagLoader
* @constructor
* @extends AbstractLoader
* @param {Object} item The item to load. Please see {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} for
* information on load items.
*/
var TagLoader = function (item, basePath) {
this.init(item, basePath);
};
var p = TagLoader.prototype = new createjs.AbstractLoader();
// Protected
/**
* The timeout that is fired if nothing is loaded after a certain delay. See the LoadQueue.LOAD_TIMEOUT
* for the timeout duration.
* @property _loadTimeout
* @type {Number}
* @private
*/
p._loadTimeout = null;
/**
* A reference to a bound function, which we need in order to properly remove the event handler when the load
* completes.
* @property _tagCompleteProxy
* @type {Function}
* @private
*/
p._tagCompleteProxy = null;
/**
* Determines if the load item is an audio tag, since we take some specific approaches to properly load audio.
* @property _isAudio
* @type {Boolean}
* @default false
*/
p._isAudio = false;
/**
* The HTML tag or JavaScript object this loader uses to preload content. Note that a tag may be a custom object
* that matches the API of an HTML tag (load method, onload callback). For example, flash audio from SoundJS passes
* in a custom object to handle preloading for Flash audio and WebAudio.
* @property _tag
* @type {HTMLAudioElement | Object}
* @private
*/
p._tag = null;
/**
* When loading a JSONP request this will be the parsed JSON result.
*
* @type {Object}
* @private
*/
p._jsonResult = null;
// Overrides abstract method in AbstractLoader
p.init = function (item, basePath) {
this._item = item;
this._basePath = basePath;
this._tag = item.tag;
this._isAudio = (window.HTMLAudioElement && item.tag instanceof HTMLAudioElement);
this._tagCompleteProxy = createjs.proxy(this._handleLoad, this);
};
/**
* Get the loaded content. This is usually an HTML tag or other tag-style object that has been fully loaded. If the
* loader is not complete, this will be null.
* @method getResult
* @return {HTMLImageElement | HTMLAudioElement | Object} The loaded and parsed content.
*/
p.getResult = function() {
if (this._item.type == createjs.LoadQueue.JSONP || this._item.type == createjs.LoadQueue.MANIFEST) {
return this._jsonResult;
} else {
return this._tag;
}
};
// Overrides abstract method in AbstractLoader
p.cancel = function() {
this.canceled = true;
this._clean();
var item = this.getItem();
};
// Overrides abstract method in AbstractLoader
p.load = function() {
var item = this._item;
var tag = this._tag;
// In case we don't get any events.
clearTimeout(this._loadTimeout); // Clear out any existing timeout
this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), createjs.LoadQueue.LOAD_TIMEOUT);
if (this._isAudio) {
tag.src = null; // Unset the source so we can set the preload type to "auto" without kicking off a load. This is only necessary for audio tags passed in by the developer.
tag.preload = "auto";
}
// Handlers for all tags
tag.onerror = createjs.proxy(this._handleError, this);
// Note: We only get progress events in Chrome, but do not fully load tags in Chrome due to its behaviour, so we ignore progress.
if (this._isAudio) {
tag.onstalled = createjs.proxy(this._handleStalled, this);
// 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.
tag.addEventListener("canplaythrough", this._tagCompleteProxy, false); // canplaythrough callback doesn't work in Chrome, so we use an event.
} else {
tag.onload = createjs.proxy(this._handleLoad, this);
tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this);
}
var src = this.buildPath(item.src, this._basePath, item.values);
// Set the src after the events are all added.
switch(item.type) {
case createjs.LoadQueue.CSS:
tag.href = src;
break;
case createjs.LoadQueue.SVG:
tag.data = src;
break;
default:
tag.src = src;
}
// If we're loading JSONP, we need to add our callback now.
if (item.type == createjs.LoadQueue.JSONP
|| item.type == createjs.LoadQueue.JSON
|| item.type == createjs.LoadQueue.MANIFEST) {
if (item.callback == null) {
throw new Error('callback is required for loading JSONP requests.');
}
if (window[item.callback] != null) {
throw new Error('JSONP callback "' + item.callback + '" already exists on window. You need to specify a different callback. Or re-name the current one.');
}
window[item.callback] = createjs.proxy(this._handleJSONPLoad, this);
}
// If its SVG, it needs to be on the DOM to load (we remove it before sending complete).
// It is important that this happens AFTER setting the src/data.
if (item.type == createjs.LoadQueue.SVG ||
item.type == createjs.LoadQueue.JSONP ||
item.type == createjs.LoadQueue.JSON ||
item.type == createjs.LoadQueue.MANIFEST ||
item.type == createjs.LoadQueue.JAVASCRIPT ||
item.type == createjs.LoadQueue.CSS) {
this._startTagVisibility = tag.style.visibility;
tag.style.visibility = "hidden";
(document.body || document.getElementsByTagName("body")[0]).appendChild(tag);
}
// Note: Previous versions didn't seem to work when we called load() for OGG tags in Firefox. Seems fixed in 15.0.1
if (tag.load != null) {
tag.load();
}
};
p._handleJSONPLoad = function(data) {
this._jsonResult = data;
};
/**
* Handle an audio timeout. Newer browsers get a callback from the tags, but older ones may require a setTimeout
* to handle it. The setTimeout is always running until a response is handled by the browser.
* @method _handleTimeout
* @private
*/
p._handleTimeout = function() {
this._clean();
var event = new createjs.Event("error");
event.text = "PRELOAD_TIMEOUT";
this._sendError(event);
};
/**
* Handle a stalled audio event. The main place we seem to get these is with HTMLAudio in Chrome when we try and
* playback 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.
};
/**
* Handle an error event generated by the tag.
* @method _handleError
* @private
*/
p._handleError = function(event) {
this._clean();
var newEvent = new createjs.Event("error");
//TODO: Propagate actual event error?
this._sendError(newEvent);
};
/**
* Handle the readyStateChange event from a tag. We sometimes need this in place of the onload event (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.getItem().tag;
// Complete is for old IE support.
if (tag.readyState == "loaded" || tag.readyState == "complete") {
this._handleLoad();
}
};
/**
* Handle a load (complete) event. This is called by tag callbacks, but also by readyStateChange and canPlayThrough
* events. Once loaded, the item is dispatched to the {{#crossLink "LoadQueue"}}{{/crossLink}}.
* @method _handleLoad
* @param {Object} [event] A load event from a tag. This is sometimes called from other handlers without an event.
* @private
*/
p._handleLoad = function(event) {
if (this._isCanceled()) { return; }
var item = this.getItem();
var tag = item.tag;
if (this.loaded || this.isAudio && tag.readyState !== 4) { return; } //LM: Not sure if we still need the audio check.
this.loaded = true;
// Remove from the DOM
switch (item.type) {
case createjs.LoadQueue.SVG:
case createjs.LoadQueue.JSONP: // Note: Removing script tags is a fool's errand.
case createjs.LoadQueue.MANIFEST:
// case createjs.LoadQueue.CSS:
//LM: We may need to remove CSS tags loaded using a LINK
tag.style.visibility = this._startTagVisibility;
(document.body || document.getElementsByTagName("body")[0]).removeChild(tag);
break;
default:
}
this._clean();
this._sendComplete();
};
/**
* Clean up the loader.
* This stops any timers and removes references to prevent errant callbacks and clean up memory.
* @method _clean
* @private
*/
p._clean = function() {
clearTimeout(this._loadTimeout);
// Delete handlers.
var tag = this.getItem().tag;
tag.onload = null;
tag.removeEventListener && tag.removeEventListener("canplaythrough", this._tagCompleteProxy, false);
tag.onstalled = null;
tag.onprogress = null;
tag.onerror = null;
//TODO: Test this
if (tag.parentNode) {
tag.parentNode.removeChild(tag);
}
var item = this.getItem();
if (item.type == createjs.LoadQueue.JSONP
|| item.type == createjs.LoadQueue.MANIFEST) {
window[item.callback] = null;
}
};
p.toString = function() {
return "[PreloadJS TagLoader]";
}
createjs.TagLoader = TagLoader;
}());
/*
* XHRLoader
* 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:
this.createjs = this.createjs || {};
(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 XHRLoader
* @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
*/
var XHRLoader = function (item, basePath) {
this.init(item, basePath);
};
var p = XHRLoader.prototype = new createjs.AbstractLoader();
//Protected
/**
* A reference to the XHR request used to load the content.
* @property _request
* @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
* @private
*/
p._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
*/
p._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
*/
p._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
*/
p._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
*/
p._rawResponse = null;
// Overrides abstract method in AbstractLoader
p.init = function (item, basePath) {
this._item = item;
this._basePath = basePath;
if (!this._createXHR(item)) {
//TODO: Throw error?
}
};
/**
* Look up the loaded result.
* @method getResult
* @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:
* 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;
if (!this._checkError()) {
this._handleError();
return;
}
this._response = this._getResponse();
this._clean();
var isComplete = this._generateTag();
if (isComplete) {
this._sendComplete();
}
};
/**
* 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 createjs.Event("error");
newEvent.text = "PRELOAD_TIMEOUT";
//TODO: Propagate actual event error
this._sendError(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 {Boolean} 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 false;
}
return true;
};
/**
* 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
//TODO: TEST
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.
* XDomainRequest
when loading cross-domain.