/*! * SoundJS * 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. */ // @ts-nocheck //############################################################################## // version.js //############################################################################## let createjs: any = window.createjs || {}; (function () { /** * Static class holding library specific information such as the version and buildDate of the library. * The SoundJS class has been renamed {{#crossLink "Sound"}}{{/crossLink}}. Please see {{#crossLink "Sound"}}{{/crossLink}} * for information on using sound. * @class SoundJS **/ var s = createjs.SoundJS = createjs.SoundJS || {}; /** * 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*/"Thu, 12 Oct 2017 16:33:45 GMT"; // injected by build process })(); //############################################################################## // extend.js //############################################################################## /** * @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); * MySubClass.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()); }; //############################################################################## // promote.js //############################################################################## /** * @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; }; //############################################################################## // deprecate.js //############################################################################## /** * @class Utility Methods */ /** * Wraps deprecated methods so they still be used, but throw warnings to developers. * * obj.deprecatedMethod = createjs.deprecate("Old Method Name", obj._fallbackMethod); * * The recommended approach for deprecated properties is: * * try { * Obj ect.defineProperties(object, { * readyOnlyProp: { get: createjs.deprecate("readOnlyProp", function() { return this.alternateProp; }) }, * readWriteProp: { * get: createjs.deprecate("readOnlyProp", function() { return this.alternateProp; }), * set: createjs.deprecate("readOnlyProp", function(val) { this.alternateProp = val; }) * }); * } catch (e) {} * * @method deprecate * @param {Function} [fallbackMethod=null] A method to call when the deprecated method is used. See the example for how * @param {String} [name=null] The name of the method or property to display in the console warning. * to deprecate properties. * @return {Function} If a fallbackMethod is supplied, returns a closure that will call the fallback method after * logging the warning in the console. */ createjs.deprecate = function(fallbackMethod, name) { "use strict"; return function() { var msg = "Deprecated property or method '"+name+"'. See docs for info."; console && (console.warn ? console.warn(msg) : console.log(msg)); return fallbackMethod && fallbackMethod.apply(this, arguments); } }; //############################################################################## // indexOf.js //############################################################################## /** * @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; }; //############################################################################## // proxy.js //############################################################################## /** * 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 */ (function() { "use strict"; /** * 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)); }; } }()); //############################################################################## // BrowserDetect.js //############################################################################## /** * @class Utility Methods */ (function() { "use strict"; /** * An object that determines the current browser, version, operating system, and other environment * variables via user agent string. * * Used for audio because feature detection is unable to detect the many limitations of mobile devices. * *

Example

* * if (createjs.BrowserDetect.isIOS) { // do stuff } * * @property BrowserDetect * @type {Object} * @param {Boolean} isFirefox True if our browser is Firefox. * @param {Boolean} isOpera True if our browser is opera. * @param {Boolean} isChrome True if our browser is Chrome. Note that Chrome for Android returns true, but is a * completely different browser with different abilities. * @param {Boolean} isIOS True if our browser is safari for iOS devices (iPad, iPhone, and iPod). * @param {Boolean} isAndroid True if our browser is Android. * @param {Boolean} isBlackberry True if our browser is Blackberry. * @constructor * @static */ function BrowserDetect() { throw "BrowserDetect cannot be instantiated"; }; var agent = BrowserDetect.agent = window.navigator.userAgent; BrowserDetect.isWindowPhone = (agent.indexOf("IEMobile") > -1) || (agent.indexOf("Windows Phone") > -1); BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1); BrowserDetect.isOpera = (window.opera != null); BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1); // NOTE that Chrome on Android returns true but is a completely different browser with different abilities BrowserDetect.isIOS = (agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1) && !BrowserDetect.isWindowPhone; BrowserDetect.isAndroid = (agent.indexOf("Android") > -1) && !BrowserDetect.isWindowPhone; BrowserDetect.isBlackberry = (agent.indexOf("Blackberry") > -1); createjs.BrowserDetect = BrowserDetect; }()); //############################################################################## // EventDispatcher.js //############################################################################## (function() { "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 * {{#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. * * Browser support * The event model in CreateJS can be used separately from the suite in any project, however the inheritance model * requires modern browsers (IE9+). * * * @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; // 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 wrapper function is returned for use with `removeEventListener` (or `off`). * * IMPORTANT: To remove a listener added with `on`, you must pass in the returned wrapper function as the listener, or use * {{#crossLink "Event/remove"}}{{/crossLink}}. Likewise, each time you call `on` a NEW wrapper function is subscribed, so multiple calls * to `on` with the same params will create multiple listeners. * *

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; iIMPORTANT: To remove a listener added with `on`, you must pass in the returned wrapper function as the listener. See * {{#crossLink "EventDispatcher/on"}}{{/crossLink}} for an example. * * @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 if necessary with the specified type. This latter approach can * be used to avoid event object instantiation for non-bubbling events that may not have any listeners. * @param {Boolean} [bubbles] Specifies the `bubbles` value when a string was passed to eventObj. * @param {Boolean} [cancelable] Specifies the `cancelable` value when a string was passed to eventObj. * @return {Boolean} Returns false if `preventDefault()` was called on a cancelable event, true otherwise. **/ p.dispatchEvent = function(eventObj, bubbles, cancelable) { if (typeof eventObj == "string") { // skip everything if there's no listeners and it doesn't bubble: var listeners = this._listeners; if (!bubbles && (!listeners || !listeners[eventObj])) { return true; } eventObj = new createjs.Event(eventObj, bubbles, cancelable); } else if (eventObj.target && eventObj.clone) { // redispatching an active event object, so clone it: eventObj = eventObj.clone(); } // TODO: it would be nice to eliminate this. Maybe in favour of evtObj instanceof Event? Or !!evtObj.createEvent 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 *
  • 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; // public methods: /** * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true if the event is cancelable. * Mirrors the DOM level 2 event standard. In general, cancelable events that have `preventDefault()` called will * cancel the default behaviour associated with the event. * @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; }()); //############################################################################## // ErrorEvent.js //############################################################################## (function() { "use strict"; /** * 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"); /** * The short error title, which indicates the type of error that occurred. * @property title * @type String */ 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; } var p = createjs.extend(ErrorEvent, createjs.Event); p.clone = function() { return new createjs.ErrorEvent(this.title, this.message, this.data); }; createjs.ErrorEvent = createjs.promote(ErrorEvent, "Event"); }()); //############################################################################## // ProgressEvent.js //############################################################################## (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"); /** * 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 = createjs.extend(ProgressEvent, createjs.Event); /** * 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); }; createjs.ProgressEvent = createjs.promote(ProgressEvent, "Event"); }(window)); //############################################################################## // LoadItem.js //############################################################################## (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; /** * 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 "Methods/GET:property"}}{{/crossLink}} or * {{#crossLink "Methods/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.Methods.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. * * @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; }()); //############################################################################## // Methods.js //############################################################################## (function() { var s = {}; /** * 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"; createjs.Methods = s; }()); //############################################################################## // Types.js //############################################################################## (function() { var s = {}; /** * 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 font files. * @property FONT * @type {String} * @default font * @static * @since 0.9.0 */ s.FONT = "font"; /** * The preload type for fonts specified with CSS (such as Google fonts) * @property FONTCSS * @type {String} * @default fontcss * @static * @since 0.9.0 */ s.FONTCSS = "fontcss"; /** * 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"; createjs.Types = s; }()); //############################################################################## // Elements.js //############################################################################## (function () { /** * Convenience methods for creating various elements used by PrelaodJS. * * @class DomUtils */ var s = {}; s.a = function() { return s.el("a"); } s.svg = function() { return s.el("svg"); } s.object = function() { return s.el("object"); } s.image = function() { return s.el("image"); } s.img = function() { return s.el("img"); } s.style = function() { return s.el("style"); } s.link = function() { return s.el("link"); } s.script = function() { return s.el("script"); } s.audio = function() { return s.el("audio"); } s.video = function() { return s.el("video"); } s.text = function(value) { return document.createTextNode(value); } s.el = function(name) { return document.createElement(name); } createjs.Elements = s; }()); //############################################################################## // DomUtils.js //############################################################################## (function () { /** * A few utilities for interacting with the dom. * @class DomUtils */ var s = { container: null }; s.appendToHead = function (el) { s.getHead().appendChild(el); } s.appendToBody = function (el) { if (s.container == null) { s.container = document.createElement("div"); s.container.id = "preloadjs-container"; var style = s.container.style; style.visibility = "hidden"; style.position = "absolute"; style.width = s.container.style.height = "10px"; style.overflow = "hidden"; style.transform = style.msTransform = style.webkitTransform = style.oTransform = "translate(-10px, -10px)"; //LM: Not working s.getBody().appendChild(s.container); } s.container.appendChild(el); } s.getHead = function () { return document.head || document.getElementsByTagName("head")[0]; } s.getBody = function () { return document.body || document.getElementsByTagName("body")[0]; } s.removeChild = function(el) { if (el.parent) { el.parent.removeChild(el); } } /** * 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; } }; createjs.DomUtils = s; }()); //############################################################################## // RequestUtils.js //############################################################################## (function () { /** * Utilities that assist with parsing load items, and determining file types, etc. * @class RequestUtils */ var s = {}; /** * 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.Types.IMAGE: case createjs.Types.BINARY: return true; default: 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.Types.TEXT: case createjs.Types.JSON: case createjs.Types.MANIFEST: case createjs.Types.XML: case createjs.Types.CSS: case createjs.Types.SVG: case createjs.Types.JAVASCRIPT: case createjs.Types.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, `createjs.Types.IMAGE`). Will return `null` if * the type can not be determined by the extension. * @static */ s.getTypeByExtension = function (extension) { if (extension == null) { return createjs.Types.TEXT; } switch (extension.toLowerCase()) { case "jpeg": case "jpg": case "gif": case "png": case "webp": case "bmp": return createjs.Types.IMAGE; case "ogg": case "mp3": case "webm": return createjs.Types.SOUND; case "mp4": case "webm": case "ts": return createjs.Types.VIDEO; case "json": return createjs.Types.JSON; case "xml": return createjs.Types.XML; case "css": return createjs.Types.CSS; case "js": return createjs.Types.JAVASCRIPT; case 'svg': return createjs.Types.SVG; default: return createjs.Types.TEXT; } }; createjs.RequestUtils = s; }()); //############################################################################## // URLUtils.js //############################################################################## (function () { /** * Utilities that assist with parsing load items, and determining file types, etc. * @class URLUtils */ 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: * * * @method parseURI * @param {String} path * @returns {Object} An Object with an `absolute` and `relative` Boolean values, * the pieces of the path (protocol, hostname, port, pathname, search, hash, host) * as well as an optional 'extension` property, which is the lowercase extension. * * @static */ s.parseURI = function (path) { var info = { absolute: false, relative: false, protocol: null, hostname: null, port: null, pathname: null, search: null, hash: null, host: null }; if (path == null) { return info; } // Inject the path parts. var parser = createjs.Elements.a(); parser.href = path; for (var n in info) { if (n in parser) { info[n] = parser[n]; } } // 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 buildURI * @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.buildURI = 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 = createjs.Elements.a(); target.href = item.src; var host = createjs.Elements.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 = createjs.Elements.a(); target.href = item.src; return target.hostname == "" && target.protocol == "file:"; }; createjs.URLUtils = s; }()); //############################################################################## // AbstractLoader.js //############################################################################## (function () { "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; // Remove these @deprecated properties after 1.0 try { Object.defineProperties(s, { POST: { get: createjs.deprecate(function() { return createjs.Methods.POST; }, "AbstractLoader.POST") }, GET: { get: createjs.deprecate(function() { return createjs.Methods.GET; }, "AbstractLoader.GET") }, BINARY: { get: createjs.deprecate(function() { return createjs.Types.BINARY; }, "AbstractLoader.BINARY") }, CSS: { get: createjs.deprecate(function() { return createjs.Types.CSS; }, "AbstractLoader.CSS") }, FONT: { get: createjs.deprecate(function() { return createjs.Types.FONT; }, "AbstractLoader.FONT") }, FONTCSS: { get: createjs.deprecate(function() { return createjs.Types.FONTCSS; }, "AbstractLoader.FONTCSS") }, IMAGE: { get: createjs.deprecate(function() { return createjs.Types.IMAGE; }, "AbstractLoader.IMAGE") }, JAVASCRIPT: { get: createjs.deprecate(function() { return createjs.Types.JAVASCRIPT; }, "AbstractLoader.JAVASCRIPT") }, JSON: { get: createjs.deprecate(function() { return createjs.Types.JSON; }, "AbstractLoader.JSON") }, JSONP: { get: createjs.deprecate(function() { return createjs.Types.JSONP; }, "AbstractLoader.JSONP") }, MANIFEST: { get: createjs.deprecate(function() { return createjs.Types.MANIFEST; }, "AbstractLoader.MANIFEST") }, SOUND: { get: createjs.deprecate(function() { return createjs.Types.SOUND; }, "AbstractLoader.SOUND") }, VIDEO: { get: createjs.deprecate(function() { return createjs.Types.VIDEO; }, "AbstractLoader.VIDEO") }, SPRITESHEET: { get: createjs.deprecate(function() { return createjs.Types.SPRITESHEET; }, "AbstractLoader.SPRITESHEET") }, SVG: { get: createjs.deprecate(function() { return createjs.Types.SVG; }, "AbstractLoader.SVG") }, TEXT: { get: createjs.deprecate(function() { return createjs.Types.TEXT; }, "AbstractLoader.TEXT") }, XML: { get: createjs.deprecate(function() { return createjs.Types.XML; }, "AbstractLoader.XML") } }); } catch (e) {} // 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 event 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); // The resultFormatter is asynchronous if (result instanceof Function) { result.call(this, createjs.proxy(this._resultFormatSuccess, this), createjs.proxy(this._resultFormatFailed, this) ); // The result formatter is synchronous } 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 toString * @return {String} a string representation of the instance. */ p.toString = function () { return "[PreloadJS AbstractLoader]"; }; createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher"); }()); //############################################################################## // AbstractMediaLoader.js //############################################################################## (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 * @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"); }()); //############################################################################## // AbstractRequest.js //############################################################################## (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); // 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"); }()); //############################################################################## // TagRequest.js //############################################################################## (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; }; 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._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) { createjs.DomUtils.appendToBody(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.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); }; /** * 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 //############################################################################## (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 //############################################################################## (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: * * 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._request.send(); } else { this._request.send(createjs.URLUtils.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. * * Note that This method uses {{#crossLink "_checkError"}}{{/crossLink}} to determine if the server has returned an * error code. * @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. * Currently this checks the status of the request for problem codes, and not actual response content: * * @method _checkError * @return {Error} An error with the status code in the `message` argument. * @private */ p._checkError = function () { var status = parseInt(this._request.status); if (status >= 400 && status <= 599) { return new Error(status); } else if (status == 0) { if ((/^https?:/).test(location.protocol)) { return new Error(0); } return null; // Likely an embedded app. } else { 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. *
    1. Some browsers get an XDomainRequest when loading cross-domain.
    2. *
    3. XMLHttpRequest are created when available.
    4. *
    5. ActiveX.XMLHTTP objects are used in older IE browsers.
    6. *
    7. Text requests override the mime type if possible
    8. *
    9. Origin headers are sent for crossdomain requests in some browsers.
    10. *
    11. 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.URLUtils.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.Methods.GET) { src = createjs.URLUtils.buildURI(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.Methods.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.Methods.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"); }()); //############################################################################## // SoundLoader.js //############################################################################## (function () { "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.Types.SOUND); // protected properties if (createjs.DomUtils.isAudioTag(loadItem)) { this._tag = loadItem; } else if (createjs.DomUtils.isAudioTag(loadItem.src)) { this._tag = loadItem; } else if (createjs.DomUtils.isAudioTag(loadItem.tag)) { this._tag = createjs.DomUtils.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 "Types/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.Types.SOUND; }; // protected methods p._createTag = function (src) { var tag = createjs.Elements.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"); }()); //############################################################################## // AudioSprite.js //############################################################################## // NOTE this is "Class" is purely to document audioSprite Setup and usage. /** * Note: AudioSprite is not a class, but its usage is easily lost in the documentation, so it has been called * out here for quick reference. * * Audio sprites are much like CSS sprites or image sprite sheets: multiple audio assets grouped into a single file. * Audio sprites work around limitations in certain browsers, where only a single sound can be loaded and played at a * time. We recommend at least 300ms of silence between audio clips to deal with HTML audio tag inaccuracy, and to prevent * accidentally playing bits of the neighbouring clips. * * Benefits of Audio Sprites: * * * Drawbacks of Audio Sprites * * *

    Example

    * * createjs.Sound.initializeDefaultPlugins(); * var assetsPath = "./assets/"; * var sounds = [{ * src:"MyAudioSprite.ogg", data: { * audioSprite: [ * {id:"sound1", startTime:0, duration:500}, * {id:"sound2", startTime:1000, duration:400}, * {id:"sound3", startTime:1700, duration: 1000} * ]} * } * ]; * createjs.Sound.alternateExtensions = ["mp3"]; * createjs.Sound.on("fileload", loadSound); * createjs.Sound.registerSounds(sounds, assetsPath); * // after load is complete * createjs.Sound.play("sound2"); * * You can also create audio sprites on the fly by setting the startTime and duration when creating an new AbstractSoundInstance. * * createjs.Sound.play("MyAudioSprite", {startTime: 1000, duration: 400}); * * The excellent CreateJS community has created a tool to create audio sprites, available at * https://github.com/tonistiigi/audiosprite, * as well as a jsfiddle to convert the output * to SoundJS format. * * @class AudioSprite * @since 0.6.0 */ //############################################################################## // PlayPropsConfig.js //############################################################################## (function () { "use strict"; /** * A class to store the optional play properties passed in {{#crossLink "Sound/play"}}{{/crossLink}} and * {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}} calls. * * Optional Play Properties Include: * * *

    Example

    * * var props = new createjs.PlayPropsConfig().set({interrupt: createjs.Sound.INTERRUPT_ANY, loop: -1, volume: 0.5}) * createjs.Sound.play("mySound", props); * // OR * mySoundInstance.play(props); * * @class PlayPropsConfig * @constructor * @since 0.6.1 */ // TODO think of a better name for this class var PlayPropsConfig = function () { // Public Properties /** * How to interrupt any currently playing instances of audio with the same source, * if the maximum number of instances of the sound are already playing. Values are defined as * INTERRUPT_TYPE constants on the Sound class, with the default defined by * {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}. * @property interrupt * @type {string} * @default null */ this.interrupt = null; /** * The amount of time to delay the start of audio playback, in milliseconds. * @property delay * @type {Number} * @default null */ this.delay = null; /** * The offset from the start of the audio to begin playback, in milliseconds. * @property offset * @type {number} * @default null */ this.offset = null; /** * How many times the audio loops when it reaches the end of playback. The default is 0 (no * loops), and -1 can be used for infinite playback. * @property loop * @type {number} * @default null */ this.loop = null; /** * The volume of the sound, between 0 and 1. Note that the master volume is applied * against the individual volume. * @property volume * @type {number} * @default null */ this.volume = null; /** * The left-right pan of the sound (if supported), between -1 (left) and 1 (right). * @property pan * @type {number} * @default null */ this.pan = null; /** * Used to create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds. * @property startTime * @type {number} * @default null */ this.startTime = null; /** * Used to create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds. * @property duration * @type {number} * @default null */ this.duration = null; }; var p = PlayPropsConfig.prototype = {}; var s = PlayPropsConfig; // Static Methods /** * Creates a PlayPropsConfig from another PlayPropsConfig or an Object. * * @method create * @param {PlayPropsConfig|Object} value The play properties * @returns {PlayPropsConfig} * @static */ s.create = function (value) { if (typeof(value) === "string") { // Handle the old API gracefully. console && (console.warn || console.log)("Deprecated behaviour. Sound.play takes a configuration object instead of individual arguments. See docs for info."); return new createjs.PlayPropsConfig().set({interrupt:value}); } else if (value == null || value instanceof s || value instanceof Object) { return new createjs.PlayPropsConfig().set(value); } else if (value == null) { throw new Error("PlayProps configuration not recognized."); } }; // Public Methods /** * Provides a chainable shortcut method for setting a number of properties on the instance. * *

    Example

    * * var PlayPropsConfig = new createjs.PlayPropsConfig().set({loop:-1, volume:0.7}); * * @method set * @param {Object} props A generic object containing properties to copy to the PlayPropsConfig instance. * @return {PlayPropsConfig} Returns the instance the method is called on (useful for chaining calls.) */ p.set = function(props) { if (props != null) { for (var n in props) { this[n] = props[n]; } } return this; }; p.toString = function() { return "[PlayPropsConfig]"; }; createjs.PlayPropsConfig = s; }()); //############################################################################## // Sound.js //############################################################################## (function () { "use strict"; /** * The Sound class is the public API for creating sounds, controlling the overall sound levels, and managing plugins. * All Sound APIs on this class are static. * * Registering and Preloading
    * Before you can play a sound, it must be registered. You can do this with {{#crossLink "Sound/registerSound"}}{{/crossLink}}, * or register multiple sounds using {{#crossLink "Sound/registerSounds"}}{{/crossLink}}. If you don't register a * sound prior to attempting to play it using {{#crossLink "Sound/play"}}{{/crossLink}} or create it using {{#crossLink "Sound/createInstance"}}{{/crossLink}}, * the sound source will be automatically registered but playback will fail as the source will not be ready. If you use * PreloadJS, registration is handled for you when the sound is * preloaded. It is recommended to preload sounds either internally using the register functions or externally using * PreloadJS so they are ready when you want to use them. * * Playback
    * To play a sound once it's been registered and preloaded, use the {{#crossLink "Sound/play"}}{{/crossLink}} method. * This method returns a {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} which can be paused, resumed, muted, etc. * Please see the {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} documentation for more on the instance control APIs. * * Plugins
    * By default, the {{#crossLink "WebAudioPlugin"}}{{/crossLink}} or the {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}} * are used (when available), although developers can change plugin priority or add new plugins (such as the * provided {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}). Please see the {{#crossLink "Sound"}}{{/crossLink}} API * methods for more on the playback and plugin APIs. To install plugins, or specify a different plugin order, see * {{#crossLink "Sound/installPlugins"}}{{/crossLink}}. * *

    Example

    * * createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio"; * createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashAudioPlugin]); * createjs.Sound.alternateExtensions = ["mp3"]; * createjs.Sound.on("fileload", this.loadHandler, this); * createjs.Sound.registerSound("path/to/mySound.ogg", "sound"); * function loadHandler(event) { * // This is fired for each sound that is registered. * var instance = createjs.Sound.play("sound"); // play using id. Could also use full source path or event.src. * instance.on("complete", this.handleComplete, this); * instance.volume = 0.5; * } * * The maximum number of concurrently playing instances of the same sound can be specified in the "data" argument * of {{#crossLink "Sound/registerSound"}}{{/crossLink}}. Note that if not specified, the active plugin will apply * a default limit. Currently HTMLAudioPlugin sets a default limit of 2, while WebAudioPlugin and FlashAudioPlugin set a * default limit of 100. * * createjs.Sound.registerSound("sound.mp3", "soundId", 4); * * Sound can be used as a plugin with PreloadJS to help preload audio properly. Audio preloaded with PreloadJS is * automatically registered with the Sound class. When audio is not preloaded, Sound will do an automatic internal * load. As a result, it may fail to play the first time play is called if the audio is not finished loading. Use * the {{#crossLink "Sound/fileload:event"}}{{/crossLink}} event to determine when a sound has finished internally * preloading. It is recommended that all audio is preloaded before it is played. * * var queue = new createjs.LoadQueue(); * queue.installPlugin(createjs.Sound); * * Audio Sprites
    * SoundJS has added support for {{#crossLink "AudioSprite"}}{{/crossLink}}, available as of version 0.6.0. * For those unfamiliar with audio sprites, they are much like CSS sprites or sprite sheets: multiple audio assets * grouped into a single file. * *

    Example

    * * var assetsPath = "./assets/"; * var sounds = [{ * src:"MyAudioSprite.ogg", data: { * audioSprite: [ * {id:"sound1", startTime:0, duration:500}, * {id:"sound2", startTime:1000, duration:400}, * {id:"sound3", startTime:1700, duration: 1000} * ]} * } * ]; * createjs.Sound.alternateExtensions = ["mp3"]; * createjs.Sound.on("fileload", loadSound); * createjs.Sound.registerSounds(sounds, assetsPath); * // after load is complete * createjs.Sound.play("sound2"); * * Mobile Playback
    * Devices running iOS require the WebAudio context to be "unlocked" by playing at least one sound inside of a user- * initiated event (such as touch/click). Earlier versions of SoundJS included a "MobileSafe" sample, but this is no * longer necessary as of SoundJS 0.6.2. * * * Loading Alternate Paths and Extension-less Files
    * SoundJS supports loading alternate paths and extension-less files by passing an object instead of a string for * the `src` property, which is a hash using the format `{extension:"path", extension2:"path2"}`. These labels are * how SoundJS determines if the browser will support the sound. This also enables multiple formats to live in * different folders, or on CDNs, which often has completely different filenames for each file. * * Priority is determined by the property order (first property is tried first). This is supported by both internal loading * and loading with PreloadJS. * * Note: an id is required for playback. * *

    Example

    * * var sounds = {path:"./audioPath/", * manifest: [ * {id: "cool", src: {mp3:"mp3/awesome.mp3", ogg:"noExtensionOggFile"}} * ]}; * * createjs.Sound.alternateExtensions = ["mp3"]; * createjs.Sound.addEventListener("fileload", handleLoad); * createjs.Sound.registerSounds(sounds); * *

    Known Browser and OS issues

    * IE 9 HTML Audio limitations
    * * * Firefox 25 Web Audio limitations * * Safari limitations
    * * * iOS 6 Web Audio limitations
    * * * Android HTML Audio limitations
    * * * Web Audio and PreloadJS
    *